如何自定义模板以不包含某些类型
How to customize template to not include certain types
在 之后,如何自定义我的模板代码使其不针对某些类型进行编译?
如果问题不清楚,请看这个例子。
///** template class ***/
template<typename T>
class testClass{
testClass();
T parameter;
}
template<typename T>
void testClass<T>::print(){cout<<parameter.value<<endl;}
以上 class 应该适用于以下类型:
//** types file **/
class paramtype1{
int value;
}
class paramtype2{
int value;
}
class paramtype3{
}
如您所见,paramtype3
没有 value
,所以我得到一个编译错误,指出 value
未定义。我知道如果我想为特定类型专门化模板 class 函数,我需要做:
template<>
void testClass<paramtype1>::print(){cout<<parameter.value<<endl;}
但是,有没有办法反过来,只排除某些类型?
如果你想要 enable/disable 完整的 class/struct,你可以使用 SFINAE 和部分专业化。
以下是C++17的例子
template <typename T, typename = void>
struct testClass;
template <typename T>
struct testClass<T, std::void_t<decltype(T::value)>>
{
testClass()
{ };
T parameter;
void print()
{ std::cout << parameter.value << std::endl; }
};
如果你只想要 enable/disable print()
函数,你必须将它模板化;举个例子
template <typename U = T>
std::void_t<decltype(U::value)> print()
{ std::cout << parameter.value << std::endl; }
或
template <typename U = T>
std::void_t<decltype(U::value), std::enable_if_t<std::is_same_v<U, T>>>
print()
{ std::cout << parameter.value << std::endl; }
如果你想确保没有人可以"hijack" 说明模板类型调用的方法
testClass<paramtype3>{}.print<paramtype1>():
为了排除使用某些类型的权限,我个人会做的是:
template <class T, class... Ts>
struct is_any : std::disjunction<std::is_same<T, Ts>...> {};
//
template <typename T>
void do_something() {
static_assert(!is_any<T, int, bool>::value, "do_something<T> cannot be used with T as int or bool");
// code here
}
允许您同时添加自定义断言消息,以便于发现错误。
在
///** template class ***/
template<typename T>
class testClass{
testClass();
T parameter;
}
template<typename T>
void testClass<T>::print(){cout<<parameter.value<<endl;}
以上 class 应该适用于以下类型:
//** types file **/
class paramtype1{
int value;
}
class paramtype2{
int value;
}
class paramtype3{
}
如您所见,paramtype3
没有 value
,所以我得到一个编译错误,指出 value
未定义。我知道如果我想为特定类型专门化模板 class 函数,我需要做:
template<>
void testClass<paramtype1>::print(){cout<<parameter.value<<endl;}
但是,有没有办法反过来,只排除某些类型?
如果你想要 enable/disable 完整的 class/struct,你可以使用 SFINAE 和部分专业化。
以下是C++17的例子
template <typename T, typename = void>
struct testClass;
template <typename T>
struct testClass<T, std::void_t<decltype(T::value)>>
{
testClass()
{ };
T parameter;
void print()
{ std::cout << parameter.value << std::endl; }
};
如果你只想要 enable/disable print()
函数,你必须将它模板化;举个例子
template <typename U = T>
std::void_t<decltype(U::value)> print()
{ std::cout << parameter.value << std::endl; }
或
template <typename U = T>
std::void_t<decltype(U::value), std::enable_if_t<std::is_same_v<U, T>>>
print()
{ std::cout << parameter.value << std::endl; }
如果你想确保没有人可以"hijack" 说明模板类型调用的方法
testClass<paramtype3>{}.print<paramtype1>():
为了排除使用某些类型的权限,我个人会做的是:
template <class T, class... Ts>
struct is_any : std::disjunction<std::is_same<T, Ts>...> {};
//
template <typename T>
void do_something() {
static_assert(!is_any<T, int, bool>::value, "do_something<T> cannot be used with T as int or bool");
// code here
}
允许您同时添加自定义断言消息,以便于发现错误。