c++ - 使用 SFINAE 和 void_t 确定容器内元素的类型

标签 c++ templates sfinae void-t

在下面的代码中,我试图通过检查容器 C 是否具有成员 value_type 来确定容器内元素的类型。 .如果为真,我将类型设置为“value_type”。然而,即使类型没有成员 value_type 并且不是容器,在传递时,编译器似乎设置了 HasMemberT_value_type 的第二个参数。为 True,即使它给出错误。

template<typename...>
using void_t = void;

template<typename T, typename = void_t<>>
struct HasMemberT_value_type : std::false_type
{
};

template<typename T>
struct HasMemberT_value_type<T, void_t<typename T::value_type>> : std::true_type
{
};

template<typename T, bool = HasMemberT_value_type<T>::value>
struct ElementTypeT
{
    using Type = typename T::value_type;
};

template<typename T>
struct ElementTypeT<T, false>
{
};

template<typename T>
using ElementType = typename ElementTypeT<T>::Type;

template<typename T>
void printType(T const& c)
{
    std::cout << "Container of " << typeid(ElementType<T>).name() << " elements.\n";
}

int main()
{                                           
    std::array<char, 5> arr;
    char classic[] = {'a', 'b', 'c', 'd'};
                                            //GNU Compiler:
    printType<arr>();                       //Container of c elements.
    printType<classic>();                   //ERROR : "In instantiation of ‘struct ElementTypeT<char [4], true>’: ... error: ‘char [4]’ is not a
                                            //         class, struct, or union type
                                            //         using Type = typename T::value_type;"

}

In instantiation of ‘struct ElementTypeT<char [4], true>

为什么设置为真??

谢谢。

最佳答案

printType<arr>()printType<classic>()不会编译。应该是printType(arr)printType(classic) .

另一个问题是ElementTypeT<T, true>有一个 Type成员(member),但是ElementTypeT<T, false>才不是。所以当你做 using ElementType = typename ElementTypeT<T>::Type并在您执行 printType(classic) 时访问它, 它会失败。

要解决此问题,请修改特化以便可以推导数组:

template<typename T, std::size_t I>
struct ElementTypeT<T[I], false>
{
    using Type=T;
};

不知道为什么 ElementTypeT<char [4], true>在你的代码中实例化。 When I ran it它出现了false对我来说。

这是使用函数重载和 SFINAE 执行此操作的更简单方法:

template<class T>
typename std::decay_t<T>::value_type get_value_type( T&& );

template<class R, std::size_t I>
R get_value_type( R(&)[I] );

template<class T>
void printType(T const& c) {
    std::cout << "Container of " << typeid(get_value_type(c)).name() << " elements.\n";
}

关于c++ - 使用 SFINAE 和 void_t 确定容器内元素的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57334992/

相关文章:

python - 如何 "install"由boost.python制作的自定义python模块

c++ - 类数组求和、索引和计算

c++ - 如何编写接受每个类和类模板的 C++ 模板?

c++ - 有没有办法从整数获取模板类型?

c++ - 返回基于参数类的模板迭代器

c++ - 成员函数声明的参数列表后的单个&符号是什么意思?

c++ - 为什么要在结构中保留内存?

c++ - 存储类初始化的模板

c++ - 如何检查嵌套模板的类型?

c++ - 为什么此自定义类型特征无法编译