为类型集专门化函数模板
Specialize function template for set of types
是否可以为不同的 集 类型创建具有不同行为的函数模板?
假设一个带有模板参数的函数,应该接受任何类型,没有编译失败
template<typename T>
void foo(T arg){
std::cout << arg;
}
当然,这不会为没有 operator<<
的类型编译。我只想在 std::cout
中编写朴素类型(即数字、std:string
、const char *
),对于其他类型,没有什么可以打印出来的。
所以,我尝试了这个(为了简化,我省略了对 std:string
、const char *
)
的检查
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
void foo(T arg){
std::cout << arg;
}
template<typename T, typename = typename std::enable_if<!std::is_arithmetic<T>::value, T>::type>
void foo(T arg){
}
也就是说,必须生成没有潜在歧义的重载函数。当然,代码不会编译,因为模板的参数不是模板签名的一部分(因此有两个模板具有相同的签名)。那么有什么办法可以玩吗?
我看到了将后者函数作为主模板的解决方案,并为声明的类型创建模板特化,但我不想用相同的定义来膨胀我的代码(并且可能会有更多类型用于打印).有什么方法可以使用 std::enable_if
或 smth 来专门化函数模板?
P.S。升压无关紧要
P.P.S。我看过这个答案 ,但我不知道如何采用它,即所有可能的类型都可以传递给函数,而不仅仅是少数预定义的
您是否尝试过使用 std::enable_if
和 return 类型的 SFINAE?
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value>::type foo(T arg)
{ std::cout << arg; }
template<typename T>
typename std::enable_if<!std::is_arithmetic<T>::value>::type foo(T arg)
{ }
或代码调度?
template <typename T>
void foo_helper (T arg, std::true_type const &)
{ std::cout << arg; }
template <typename T>
void foo_helper (T arg, std::false_type const &)
{ }
template <typename T>
void foo (T arg)
{ foo_helper(arg, std::is_arithmetic<T>{}); }
(注意:代码未经测试)
您可以直接对 SFINAE 使用所需的表达式 std::cout << arg
。示例:
template<typename T>
auto foo_imp(T&& arg, int) -> decltype(std::cout << std::forward<T>(arg), throw) /* -> is void */ {
std::cout << std::forward<T>(arg);
}
template<typename T>
void foo_imp(T&&, long) {
// Do nothing.
}
template<typename T>
void foo(T&& arg) {
foo_imp(std::forward<T>(arg), 0); // int is the best match for 0.
}
struct X {};
int main() {
foo(1); // calls foo_imp(int&&, int)
foo(X{}); // calls foo_imp(X&&, long)
}
上面std::forward
用来迂腐地保留arg
的值类。
试试这个:
#include <iostream>
template<typename T, typename std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
void foo(T arg){
std::cout << arg << '\n';
}
template<typename T, typename std::enable_if_t<!std::is_arithmetic<T>::value, int> = 0>
void foo(T arg){
std::cout << "not an arithmetic type\n";
}
int main() {
foo(4.6);
foo("bla");
}
这需要 C++14(对 C++11 使用 std::enable_if
),并输出:
4.6
not an arithmetic type
有什么区别?
如果满足条件,我们在这里创建一个默认值为 0 的 int
作为第二个模板参数。
是否可以为不同的 集 类型创建具有不同行为的函数模板?
假设一个带有模板参数的函数,应该接受任何类型,没有编译失败
template<typename T>
void foo(T arg){
std::cout << arg;
}
当然,这不会为没有 operator<<
的类型编译。我只想在 std::cout
中编写朴素类型(即数字、std:string
、const char *
),对于其他类型,没有什么可以打印出来的。
所以,我尝试了这个(为了简化,我省略了对 std:string
、const char *
)
template<typename T, typename = typename std::enable_if<std::is_arithmetic<T>::value, T>::type>
void foo(T arg){
std::cout << arg;
}
template<typename T, typename = typename std::enable_if<!std::is_arithmetic<T>::value, T>::type>
void foo(T arg){
}
也就是说,必须生成没有潜在歧义的重载函数。当然,代码不会编译,因为模板的参数不是模板签名的一部分(因此有两个模板具有相同的签名)。那么有什么办法可以玩吗?
我看到了将后者函数作为主模板的解决方案,并为声明的类型创建模板特化,但我不想用相同的定义来膨胀我的代码(并且可能会有更多类型用于打印).有什么方法可以使用 std::enable_if
或 smth 来专门化函数模板?
P.S。升压无关紧要
P.P.S。我看过这个答案
您是否尝试过使用 std::enable_if
和 return 类型的 SFINAE?
template<typename T>
typename std::enable_if<std::is_arithmetic<T>::value>::type foo(T arg)
{ std::cout << arg; }
template<typename T>
typename std::enable_if<!std::is_arithmetic<T>::value>::type foo(T arg)
{ }
或代码调度?
template <typename T>
void foo_helper (T arg, std::true_type const &)
{ std::cout << arg; }
template <typename T>
void foo_helper (T arg, std::false_type const &)
{ }
template <typename T>
void foo (T arg)
{ foo_helper(arg, std::is_arithmetic<T>{}); }
(注意:代码未经测试)
您可以直接对 SFINAE 使用所需的表达式 std::cout << arg
。示例:
template<typename T>
auto foo_imp(T&& arg, int) -> decltype(std::cout << std::forward<T>(arg), throw) /* -> is void */ {
std::cout << std::forward<T>(arg);
}
template<typename T>
void foo_imp(T&&, long) {
// Do nothing.
}
template<typename T>
void foo(T&& arg) {
foo_imp(std::forward<T>(arg), 0); // int is the best match for 0.
}
struct X {};
int main() {
foo(1); // calls foo_imp(int&&, int)
foo(X{}); // calls foo_imp(X&&, long)
}
上面std::forward
用来迂腐地保留arg
的值类。
试试这个:
#include <iostream>
template<typename T, typename std::enable_if_t<std::is_arithmetic<T>::value, int> = 0>
void foo(T arg){
std::cout << arg << '\n';
}
template<typename T, typename std::enable_if_t<!std::is_arithmetic<T>::value, int> = 0>
void foo(T arg){
std::cout << "not an arithmetic type\n";
}
int main() {
foo(4.6);
foo("bla");
}
这需要 C++14(对 C++11 使用 std::enable_if
),并输出:
4.6
not an arithmetic type
有什么区别?
如果满足条件,我们在这里创建一个默认值为 0 的 int
作为第二个模板参数。