17

我怎么static_assert喜欢这个?如果不是 C++ 或 C++11 中的新功能,也许 Boost 支持它?

template<T>
struct foo {};

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

3 回答 3

31

你可以按照这些思路做一些事情。给定一个可以验证类是否是类模板的实例化的特征:

#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 { };

在您的程序中按如下方式使用它:

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<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!
}

这是一个活生生的例子

于 2013-06-30T13:10:43.220 回答
2

对其他答案的一些小改进:

  • 该名称实际上对参数的顺序有意义
  • 通过 std::decay 正确处理constvolatile和引用类型
  • 实现 C++14 风格的 _vconstexpr变量
  • 接受任意数量的类型进行测试(测试 ALL)

我故意不将 std::decay_t 放在 is_template_for_v 上,因为无论是否使用 _v 后缀调用类型特征,它的工作方式都应该相同。

这确实需要 C++17 ,但您可以删除可变参数功能或使用 c++11/14std::conjunction实现自己的功能。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
于 2017-10-29T07:15:59.440 回答
0

正如别人所写,

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 { };

但是,请注意,这仅适用于模板参数都是类型名的模板类!

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

它根本无法编译。

我相信 C++11/C++14/C++17 目前没有办法处理这个限制。

于 2013-08-20T02:10:16.763 回答