2017-06-18 58 views
3

給定一個 「正常」 的模板:如何檢測模板是否是別名模板?

template<typename> struct Normal; 

和別名模板:

template<typename> 
using Alias = void; 

我如何,當作爲模板的模板參數給出,這兩個區別?

所以,最好我想下面的編譯:

int main() { 
    static_assert( is_alias_template<Alias>::value, ""); 
    static_assert(! is_alias_template<Normal>::value, ""); 
} 

回答

4

一個可行的方法就是利用這一點:

別名模板永遠不會被模板參數推導得出推斷模板的模板時參數。

http://en.cppreference.com/w/cpp/language/type_alias

因此,與類型特徵像

template< 
    typename T, 
    template<typename...> class Template 
    > 
struct instantiated_from 
    : std::false_type {}; 

template< 
    template<typename...> class Template, 
    typename... Arguments 
    > 
struct instantiated_from<Template<Arguments...>, Template> 
    : std::true_type {}; 

我們可以肯定的是,當我們通過Alias<int>作爲第一個模板參數和Alias爲第二,那麼編譯器不會選擇專業化。這立即給我們:

template< 
    template<typename...> class Template, 
    typename... Args 
    > 
struct is_alias_template 
    : std::integral_constant< 
     bool, 
     ! instantiated_from<Template<Args...>, Template>::value 
     > 
{}; 

有了這個,我們可以 - 給出一些合適的模板參數 - 檢測模板是否爲別名模板或不:

int main() { 
    static_assert( is_alias_template<Alias, int>::value, ""); 
    static_assert(! is_alias_template<Normal, int>::value, ""); 

    static_assert( is_alias_template<Alias, Alias<int>>::value, ""); 
    static_assert( is_alias_template<Alias, Normal<int>>::value, ""); 
    static_assert(! is_alias_template<Normal, Alias<int>>::value, ""); 
    static_assert(! is_alias_template<Normal, Normal<int>>::value, ""); 
} 

這裏的主要缺點是當然的那個人需要知道一組合適的模板參數。只是猜測(或使用int)將不適用於具有固定號碼(> 1)模板參數的模板。

此外,這不適用於具有非類型(或模板)模板參數的模板(別名或不模板)。