模板中的默认参数 - >模板参数涉及模板参数

时间:2015-06-02 08:29:44

标签: c++ templates c++11

我遇到类似这样的问题:SFINAE tried with bool gives compiler error: "template argument ‘T::value’ involves template parameter"

我想定义一个特征,告诉复杂的表示是否是一个结构数组,其中实际值永远不是AoS,因此不需要用户定义的规范,但对于复杂的,你总是需要一个:

/**
 * Evaluates to a true type if the given complex type is an Array of Structs, false otherwise
 * Defaults to false for Real values
 */
template< typename T, bool T_isComplex = IsComplex<T>::value >
struct IsAoS: std::false_type{};

/**
 * Undefined for (unknown) complex types
 */
template< typename T >
struct IsAoS< T, true >;

通过从std :: true / false_type派生,以标准方式完成专业化。

问题是:通过这个实现,我得到&#34;模板参数涉及模板参数&#34;错误(在链接问题中解释)但是如果我切换到类型(在第一个模板中省略&#34; ::值&#34;在第二个模板中将true更改为true_type)复杂类型不匹配第二个模板因为唯一的派生自std :: true_type而且不是std :: true_type。

我能想到的唯一解决方案是使用表达式SFINAE并将主模板的第二个参数更改为默认值void,将实例更改为enable_if(isComplex == false)。还有什么更好的吗?

2 个答案:

答案 0 :(得分:2)

如果我理解正确,你想:

template<class> struct IsComplex_impl  {using type = std::false_type;};
template<class T> struct IsComplex_impl<std::complex<T>> {using type = std::true_type;};

template <typename T>
using IsComplex =  typename IsComplex_impl<T>::type;

// Declaration only
template<typename T, typename T_isComplex = IsComplex<T>>
struct IsAoS;

// general case
template< typename T >
struct IsAoS< T, std::false_type >: std::false_type{};

// specialization for complex<double>
template<>
struct IsAoS< std::complex<double>>: std::true_type{};

Live Demo

或使用相同的签名:

template<class> struct IsComplex_impl : std::false_type {};
template<class T> struct IsComplex_impl<std::complex<T>> : std::true_type {};

template <typename T>
constexpr bool IsComplex() {return IsComplex_impl<T>::value;}

// Declaration only
template<typename T, bool T_isComplex = IsComplex<T>()>
struct IsAoS;

// general case
template< typename T >
struct IsAoS< T, false>: std::false_type{};

// specialization for complex<double>
template<>
struct IsAoS< std::complex<double>>: std::true_type{};

Live Demo

答案 1 :(得分:2)

假设IsAoS<T>所需的行为是:

  • 如果IsComplex<T>::valuefalse,则默认为false_type;
  • 否则,除非用户提供专业化,否则将出现错误。

使用static_assert可以直接实现;不需要默认模板参数:

template< typename T >
struct IsAoS: std::false_type {
    static_assert(!IsComplex<T>::value, "A user specialization must be provided for Complex types");
};

如果你想要默认参数技巧,只需使用包装层:

namespace detail {

    template< typename T, bool T_isComplex = IsComplex<T>::value >
    struct IsAoS_impl: std::false_type{};

    /**
     * Undefined for (unknown) complex types
     */
    template< typename T >
    struct IsAoS_impl< T, true >;
}

template<class T> struct IsAoS : detail::IsAoS_impl<T> {};

用户应该专攻IsAoS