使用static_assert来确定特定模板参数是否为特定的非类型化类模板
Using a static_assert to determine if a specific template parameter is a specific untyped class template
我想要一个函数,将参数限制为仅从特定模板类派生的类型。在这种情况下,basic_string
(来自STL文档)。例如,声明一个wstring
:
typedef basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >
wstring;
基本想法是这样的:
template <class TString>
void strings_only_please(TString message) {
static_assert(is_base_of<basic_string, TString>::value,
"Not a string type!");
}
当然,这不会编译,尽管还没有指定basic_string。。。它需要一个真正的类型。(虽然我可能只是对少数实际的字符串类型进行硬编码,但我正在寻找这种模式的通用解决方案。)
我使用的是Visual Studio 2012,理想情况下希望代码能够移植到其他现代C++编译器,如GCC。
有三种解决问题的方法,一种是实现is_specialization_of
,另一种是使函数采用std::basic_string<T1,T2,T3>
而不是TString
,第三种方法与第二种解决方案具有相同的原理;使模板仅可由CCD_ 6匹配。
is_base_of
在您的示例中是不够的,原因有两个:
-
is_base_of
用于查看类型U
是否派生自T
(或者是否为同一类型),在您的代码段中不涉及继承。 -
std::basic_string
不是一个完整的类型,因此根本不能与is_base_of
一起使用(您已经指出了这一点)。
解决方案#1
is_specialization_of
将用于检查类型U
是否是不完整类型T
的专门化。使用模板模板类很容易实现它,如下例所示。
正如@SebastianRedl所指出的,使用VS2012无法获得可变模板,请参阅其他解决方案(这些解决方案不是通用的,但仍然足以满足您的需求)
#include <type_traits>
#include <iostream>
#include <string>
template<template<typename...> class T, typename U>
struct is_specialization_of : std::false_type { };
template<template<typename...> class T, typename... Ts>
struct is_specialization_of<T, T<Ts...>> : std::true_type { };
int
main (int argc, char *argv[])
{
std::cerr << is_specialization_of<std::basic_string, std::string >::value << std::endl;
std::cerr << is_specialization_of<std::basic_string, std::wstring>::value << std::endl;
std::cerr << is_specialization_of<std::basic_string, std::istream>::value << std::endl;
}
输出
1
1
0
解决方案#2
template <typename T1, typename T2, typename T3>
void strings_only_please(std::basic_string<T1,T2,T3>) {
// ...
}
当然,以上不会导致很好的static_assert
错误,但它足以满足您的需求,并满足您的要求;该函数只能由专门化CCD_ 17的类型调用。
解决方案#3
template<typename T>
struct is_basic_string : std::false_type { };
template<typename T1, typename T2, typename T3>
struct is_basic_string<std::basic_string<T1,T2,T3>> : std::true_type { };
...
is_basic_string<std::string >::value // true
is_basic_string<std::istream>::value // false
- 在提升multi_index容器中,是否定义了"default index"?
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 检查输入是否不是整数或数字
- 是否可以初始化不可复制类型的成员变量(或基类)
- 在C++中,是否可以基于给定的标识符创建基类的新实例,反之亦然
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 此代码是否违反一个定义规则
- 是否需要删除包含对象的"pair"?
- 是否可以从int转换为enum类类型
- 无论条件是否为true,if总是在c++中执行
- 如何找到大小'x'数组是否完全填充,在C++?
- 检查值是否在集合p1和p2中,但不在p3中
- 是否可以在编译时初始化数组,以便在运行时不会花费时间?
- 将指向类型化/大小的枚举的指针转换为指向基础类型的指针是否安全?
- 返回间接类型化对象是否会影响性能
- 是否可以对基于字符串的用户定义文本进行强类型化
- 如何检查 chaiscript 中是否定义了函数以及如何使用类型化参数执行它
- 是否可以在C++Actor框架中对类型化的Actor使用继承
- 使用static_assert来确定特定模板参数是否为特定的非类型化类模板
- 文章泛型<Programming>类型化缓冲区在 C++ 11 中是否完全过时?