C++ 模板化参数包在 gcc/clang 上编译,在 MSVC 上出错

问题描述 投票:0回答:1

我已将我的错误归结为这种情况。我有一个基于 maplibre-gl 中的变体代码的自定义变体片段。它继承自

std::variant
,并对其自己的构造函数进行了一些额外的模板检查。我将自己的
BaseVariant
定义为该变体的实例,然后定义两个类:直接从
ValueFromBaseVariant
继承的
BaseVariant
和通过
ValueFromDerivedVariant
BaseVariant
继承的
DerivedVariant
(它是空的,但是继承
BaseVariant
构造函数):

#include <functional>
#include <tuple>
#include <type_traits>
#include <variant>

namespace maplibre {

template <typename T, typename... Types>
struct DirectType {
    static constexpr bool is_direct = (std::is_same_v<T, Types> || ...);
};

template <typename T, typename... Types>
struct ConvertibleType {
    static constexpr bool is_convertible = (std::is_convertible<T, Types>::value || ...);
};

template <typename T, typename... Types>
struct ValueTraits {
    using ValueType = typename std::remove_const<typename std::remove_reference<T>::type>::type;
    static constexpr bool is_valid = DirectType<ValueType, Types...>::is_direct || ConvertibleType<ValueType, Types...>::is_convertible;
};

template <typename... Types>
class variant : public std::variant<Types...> {
private:
    using base_variant = std::variant<Types...>;
    using current_variant = variant<Types...>;

public:
    variant() : base_variant() {}

    template <typename T,
              typename CurrentTraits = ValueTraits<T, Types...>,
              typename Enabled = typename std::enable_if<CurrentTraits::is_valid && !std::is_same_v<current_variant, typename CurrentTraits::ValueType>>::type>
    variant(T&& val) : base_variant(std::forward<T>(val)) {}
};
} // namespace maplibre


using BaseVariant = maplibre::variant<bool, int>;

class DerivedVariant : private BaseVariant {
  public:
    using BaseVariant::BaseVariant;
};


// Works for all compilers
class ValueFromBaseVariant : public BaseVariant
{
public:
    ValueFromBaseVariant(bool b) : BaseVariant(b) {}
};

// Works for gcc/clang, error for MSVC
class ValueFromDerivedVariant : public DerivedVariant
{
public:
    ValueFromDerivedVariant(bool b) : DerivedVariant(b) {}
};


在我尝试过的所有编译器(clang、gcc、msvc)上,

ValueFromBaseVariant
编译正常。但
ValueFromDerivedVariant
只能在 clang 和 gcc 上编译。使用 msvc 会出现以下错误:

example.cpp
<source>(60): error C2665: 'DerivedVariant::DerivedVariant': no overloaded function could convert all the argument types
<source>(46): note: could be 'DerivedVariant::DerivedVariant(DerivedVariant &&)'
<source>(60): note: 'DerivedVariant::DerivedVariant(DerivedVariant &&)': cannot convert argument 1 from 'bool' to 'DerivedVariant &&'
<source>(60): note: Reason: cannot convert from 'bool' to 'DerivedVariant'
<source>(46): note: or       'DerivedVariant::DerivedVariant(const DerivedVariant &)'
<source>(60): note: 'DerivedVariant::DerivedVariant(const DerivedVariant &)': cannot convert argument 1 from 'bool' to 'const DerivedVariant &'
<source>(60): note: Reason: cannot convert from 'bool' to 'const DerivedVariant'
<source>(46): note: or       'DerivedVariant::DerivedVariant(void)'
<source>(60): note: 'DerivedVariant::DerivedVariant': function does not take 1 arguments
<source>(45): note: or       'DerivedVariant::DerivedVariant(T &&)', which inherits 'maplibre::variant<bool,int>::variant(T &&)' via base class 'maplibre::variant<bool,int>'
<source>(60): note: 'DerivedVariant::DerivedVariant(T &&)': could not deduce template argument for 'CurrentTraits'
<source>(60): note: 'Types': parameter pack cannot be used in this context
<source>(60): note: while trying to match the argument list '(bool)'
Compiler returned: 2

神箭链接: msvc:https://godbolt.org/z/sv99qnn9P 海湾合作委员会:https://godbolt.org/z/5soz1oMeh

我是否做错了什么并且 gcc/clang 很宽松,或者 msvc 缺少什么?谢谢

c++ templates visual-c++
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.