2013-06-30 98 views
13

我如何static_assert這樣?也許Boost支持它,如果不是C++或C++ 11中的新特性?做一個static_assert,模板類型是另一個模板

template<T> 
struct foo {}; 

template<FooType> 
struct bar { 
    static_assert(FooType is indeed foo<T> for some T,"failure"); //how? 
}; 
+0

一個相關的問題都可以找到[這裏](HTTP://計算器。com/questions/12919310/c-detect-templated-class/12919396) –

回答

23

你可以沿着這些線做些事情。給定一個特點是可以驗證類是否是一個類模板的一個實例:

template<typename T> 
struct foo {}; 

template<typename FooType> 
struct bar { 
    static_assert(is_instantiation_of<FooType, foo>::value, "failure"); 
}; 

int main() 
{ 
    bar<int> b; // ERROR! 
    bar<foo<int>> b; // OK! 
} 

如果你願意,你可以概括這個檢測是否:

#include <type_traits> 

template<typename T, template<typename> class TT> 
struct is_instantiation_of : std::false_type { }; 

template<typename T, template<typename> class TT> 
struct is_instantiation_of<TT<T>, TT> : std::true_type { }; 

在你的程序如下使用它一類是模板的任意數量的(類型)參數的情況下,像這樣:

#include <type_traits> 

template<template<typename...> class TT, typename T> 
struct is_instantiation_of : std::false_type { }; 

template<template<typename...> class TT, typename... Ts> 
struct is_instantiation_of<TT, TT<Ts...>> : std::true_type { }; 

template<typename FooType> 
struct bar { 
    static_assert(is_instantiation_of<foo, FooType>::value, "failure"); 
}; 

你會然後用它在你的程序是這樣的:

template<typename FooType> 
struct bar { 
    static_assert(is_instantiation_of<foo, FooType>::value, "failure"); 
}; 

int main() 
{ 
    bar<int> b; // ERROR! 
    bar<foo<int>> b; // OK! 
} 

這是live example

+0

你(或這裏的其他人)是否認爲通過Vandevoorde和Josuttis讀的書「C++模板:完全指南」的知識可以讓我做這是我自己的? –

+0

嗯,可能不會,因爲'std :: true_type'是一個C++ 11功能:(似乎沒有任何新的模板書籍圍繞C++ 11 –

+1

@ roger.james:這是一個很好的但是,正如你所提到的,在這個答案中,我使用了C++ 11中沒有提供的特性(尤其是可變參數模板)。 –

1

至於別人寫的,

template<typename T, template<typename...> class TT> 
struct is_specialization_of : std::false_type { }; 

template<template<typename...> class TT, typename... Ts> 
struct is_specialization_of<TT<Ts...>, TT> : std::true_type { }; 

然而,當心,這僅適用於模板類其模板參數都是typenames!

typedef std::array<int, 42> MyArray; 
static_assert(is_specialization_of<MyArray, std::array>::value, ""); 

主辦便索性無法在所有編譯。

我相信C++ 11/C++ 14/C++ 17目前無法處理這個限制。

+0

This不是答案。複製/粘貼他人的答案,然後評論它並不是一個合適的答案。如果您對某人的回答有評論,請對他們的回答留言。 – xaxxon

+0

誰是「別人」?請更新此答案,以便向您複製此代碼的人提供正確的[歸屬地](https://stackoverflow.blog/2009/06/25/attribution-required/)。是[Xeo的答案在這裏](https://stackoverflow.com/a/12919396)還是其他答案? –

+0

歡迎來到2017年,你們兩個! :)如果你喜歡,可以自由地將「別人」編輯爲「Andy Prowl」。 – Quuxplusone

0

一些小的改進,在其他的答案:

  • 名稱實際上使有關參數
  • 妥善處理constvolatile,而引用類型通過的std ::衰變
  • 農具的秩序感C++ 14樣式_v constexpr變量
  • 接受任意數量的類型進行測試(ALL測試)

我有意不把std :: decay_t放在is_template_for_v上,因爲類型特徵應該同樣地工作,不管它是否用_v後綴調用。

這確實需要C++ 17的std::conjunction,但您可以刪除可變參數或使用C++ 11/14實現自己的conjunction

template<template<class...> class tmpl, typename T> 
struct _is_template_for : public std::false_type {}; 

template<template<class...> class tmpl, class... Args> 
struct _is_template_for<tmpl, tmpl<Args...>> : public std::true_type {}; 

template<template<class...> class tmpl, typename... Ts> 
using is_template_for = std::conjunction<_is_template_for<tmpl, std::decay_t<Ts>>...>; 

template<template<class...> class tmpl, typename... Ts> 
constexpr bool is_template_for_v = is_template_for<tmpl, Ts...>::value; 

用法:

static_assert(is_template_for_v<std::vector, std::vector<int>>); // doesn't fire 
相關問題