2013-06-30 96 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 
相关问题