使用带有is_class的std :: conditional ,出现编译错误

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

我想拥有一个依赖于其他具有X :: value_type的其他类X的类型。如果另一个类中没有这样的typedef,我只想单独使用X。

所以我正在寻找类似的代码:

TypeChecker<X>::value_type  // Here, value_type might be X or X::value_type, depending on X.

但是我最初的尝试失败了,请参见下文:

这里是无法编译的程序:

#include<type_traits>

template<typename T>
struct TypeChecker {
    typedef typename std::conditional<
        std::is_class<T>::value,
        typename T::value_type,  // I believe the error is due to this line (could be wrong)
        T>::type value_type;
};

int main()
{
    TypeChecker<int>::value_type x = 3;

    return 0;
}

它给出:error: 'int' is not a class, struct, or union type

您可以在线尝试:godbolt link

我很困惑,因为我认为std::conditional会选择正确的分支,但从某种意义上讲,它似乎正在评估这两个分支。至少足以引起编译错误。

帮助?

c++ c++14 sfinae
2个回答
0
投票

问题是T::value_type作为模板参数传递给std::conditional,当Tint时表达式本身无效。

您可以使用类模板和部分专业化来代替。

template<typename T, typename = void>
struct TypeChecker {
    typedef T value_type;
};
template<typename T>
struct TypeChecker<T, typename std::enable_if<std::is_class<T>::value>::type> {
    typedef typename T::value_type value_type;
};

BTW:std::is_class似乎很松散;您可以将其约束为具有成员类型value_type,例如

template<typename T, typename = void>
struct TypeChecker {
    typedef T value_type;
};
template<typename T>
struct TypeChecker<T, std::void_t<typename T::value_type>> {
    typedef typename T::value_type value_type;
};

0
投票

std::conditional不“短路”。为了甚至将std::conditional<C,X,Y>实例化为类类型,三个模板参数必须全部为实际类型。没有一种模板可以与代表非法或未知类型的模板参数之一一起使用,即使该参数没有直接关系。

TypeChecker的某些解决方案:

// C++14 or C++17, using partial specialization SFINAE:
template <typename T, typename Enable = void>
struct TypeChecker {
    using value_type = T;
};
template <typename T>
struct TypeChecker<T, std::void_t<typename T::value_type>> {
    using value_type = typename T::value_type;
};        

// C++11 or later, using function SFINAE:
template <typename T>
struct type_identity { using type = T; };
template <typename T>
type_identity<typename T::value_type> TypeChecker_helper(int); // not defined
template <typename T>
type_identity<T> TypeChecker_helper(...); // not defined
template <typename T>
struct TypeChecker {
    using value_type = typename decltype(TypeChecker_helper<T>(0))::type;
};

((此外:我对自动“解开”事物的模板总是有点怀疑,像TypeChecker。它可能会阻碍特别想直接使用容器或迭代器作为值的代码。)

© www.soinside.com 2019 - 2024. All rights reserved.