有三种方法可以解决您的问题,一种是 的实现is_specialization_of
,另一种是让您的函数采用 astd::basic_string<T1,T2,T3>
而不是TString
,第三种方法与第二种解决方案具有相同的理念;使模板只能由std::basic_string
.
is_base_of
由于两个原因,在您的示例中还不够:
is_base_of
用于查看类型U
是否派生自T
(或是否为同一类型),在您的代码段中不涉及继承。
std::basic_string
不是一个完整的类型,因此根本不能使用is_base_of
(您已经指出)。
解决方案#1
is_specialization_of
将用于检查 type 是否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
错误 - 但它足以满足您的需求并满足您的需求;该函数只能由专门的类型调用std::basic_string
。
解决方案#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