有三种方法可以解决您的问题,一种是 的实现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