首页 文章

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

提问于
浏览
3

我有一个与此类似的问题: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派生,以标准方式完成特化 .

问题是:通过这个实现,我得到“模板参数涉及模板参数”错误(在链接问题中解释)但是如果我切换到类型(在第一个模板中省略“:: value”并将true更改为第二个中的true_type)复杂类型将不再与第二个模板匹配,因为唯一派生自std :: true_type且ARE NOT std :: true_type .

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

2 回答

  • 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 .

  • 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

相关问题