简体   繁体   English

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

[英]Using SFINAE and void_t to determine type of elements inside a container

In the code below, I'm trying to determine the type of elements inside a container by checking whether a container C has member value_type . 在下面的代码中,我试图通过检查容器C是否具有成员value_type来确定容器内元素的类型。 If true, I set the type to "value_type". 如果为true,则将类型设置为“ value_type”。 However even when a type doesn't have member value_type and isn't a container, when passed, compiler seems to set the second argument of HasMemberT_value_type to True, even though it gives error. 但是,即使当类型没有成员value_type且不是容器时,通过时,编译器似乎HasMemberT_value_typeHasMemberT_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>

why is it set to true?? 为什么将其设置为true?

Thank you. 谢谢。

printType<arr>() and printType<classic>() won't compile. printType<arr>()printType<classic>()无法编译。 It should be printType(arr) and printType(classic) . 它应该是printType(arr)printType(classic)

The other problem is that ElementTypeT<T, true> has a Type member, but ElementTypeT<T, false> does not. 另一个问题是ElementTypeT<T, true>具有Type成员,而ElementTypeT<T, false>没有。 So when you do using ElementType = typename ElementTypeT<T>::Type and access that when you do printType(classic) , it will fail. 因此,当您using ElementType = typename ElementTypeT<T>::Type并在执行printType(classic)时访问它时,它将失败。

To fix this, modify the specialization so that the array can be deduced: 要解决此问题,请修改特殊化,以便可以推导数组:

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

Not sure why ElementTypeT<char [4], true> is instaniating in your code. 不知道为什么在您的代码中实例化ElementTypeT<char [4], true> When I ran it it came up false for me. 当我运行它时,对我来说是false的。

Here's a simpler way to do this using function overloading and SFINAE: 这是使用函数重载和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";
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM