2015-06-02 196 views
2

我有類似這樣的一個問題: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-方式通過的std ::真/ false_type獲得完成。

問題是:在這個實現中,我得到了「模板參數涉及到模板參數」錯誤(在鏈接問題中解釋過),但是如果我切換到類型(在第一個模板中省略「並在第二個變爲true_type)複合類型將不再匹配第二個模板,因爲唯一的派生自std :: true_type,而不是std :: true_type。

我唯一能想到的解決方案是使用表達式SFINAE,並將主模板的第二個參數更改爲默認的void和enable_if(isComplex == false)。有什麼更好的?

+1

[你的代碼應該沒問題](http://coliru.stacked-crooked.com/a/cb2dee9c0e1ff3ed),這實際上是一種相當普遍的技術。你正在使用哪個編譯器,哪個版本? –

+0

那麼,你修改了代碼,使IsAoS默認爲true,對於所有錯誤/危險的複雜類型。我的例子:http://coliru.stacked-crooked.com/a/086450479bc561db – Flamefire

+0

編譯器的要點是你不能寫'struct IsAoS >',並使用主模板的默認模板參數填補這個部分專業化的第二個參數,因爲那取決於'T',所以是不允許的。 (導致錯誤的代碼段應該真的存在於你的問題中。)期望的行爲是什麼 - 默認爲'false_type',除非'IsComplex :: value'爲'true',在這種情況下,除非用戶提供專門化,否則它應該是錯誤的? –

回答

1

在那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

+0

我認爲這是最好的解決方案。很好,很乾淨 – Flamefire

1

如果我理解正確的話,你想:

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

+0

這不會改變問題:http://coliru.stacked-crooked.com/a/a6e11b72a78d52fc – Flamefire

+0

@Flamefire:通過更改'IsAoS'原型來修正編譯。 – Jarod42

+0

第一個版本的確可以工作,儘管嵌套類型的ssems非常難看,一旦只能繼承true/false_type。不過,我可以改變使用一個新的實例integral_type 這應該工作(?)第二個版本不適用於部分專業化(複雜) – Flamefire