当方法可用时,我如何专门化模板?
How I can specialize template when a method is available?
我想知道当我的类型具有特定方法时,我如何才能拥有专门的模板。我们以下面的代码为例:
template<typename T, typename... Args>
void foo(T&& arg, Args&&... args)
{
std::cout << "called 1\n";
}
template<typename T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::log)>, int> = 0>
void foo(T&& v)
{
v.log();
}
struct Y
{
void log() const
{
std::cout << "called 2\n";
}
};
int main()
{
foo(1); // <-- print "called 1";
Y y;
foo(y); // <-- print "called 2";
}
我应该说这段代码不起作用(第二个 foo
将使用主模板并打印 called 1
)而且我知道我不能部分特化函数调用,但它显示了我需要的.
知道如何实现这样的目标吗?我应该使用结构进行部分特化然后使用辅助函数吗?
你不需要那么冗长;您可以启用另一个 foo
,方法如下:
template<typename T>
auto foo(T&& v) -> decltype(v.log(), void())
{
v.log();
}
这叫做trailing return type. You provide the decltype
to evaluate the expressions (1. v.log()
, 2. void()
) with comma operator分离。如果第一个表达式(即 v.log()
)失败,则重载不适合调用。因此,它适用于另一个 foo
。否则,它接受带有 void
return 的重载,这是从 void()
表达式求值的!
你走的很好,但是,转发参考,
decltype(&T::log)
变为 decltype(&(Y&)::log)
无效。
使用 std::decay
解决了您的问题:
template<typename T,
std::enable_if_t<
std::is_member_function_pointer_v<decltype(&std::decay_t<T>::log)>,
int> = 0>
void foo(T&& v)
{
v.log();
}
我想知道当我的类型具有特定方法时,我如何才能拥有专门的模板。我们以下面的代码为例:
template<typename T, typename... Args>
void foo(T&& arg, Args&&... args)
{
std::cout << "called 1\n";
}
template<typename T, std::enable_if_t<std::is_member_function_pointer_v<decltype(&T::log)>, int> = 0>
void foo(T&& v)
{
v.log();
}
struct Y
{
void log() const
{
std::cout << "called 2\n";
}
};
int main()
{
foo(1); // <-- print "called 1";
Y y;
foo(y); // <-- print "called 2";
}
我应该说这段代码不起作用(第二个 foo
将使用主模板并打印 called 1
)而且我知道我不能部分特化函数调用,但它显示了我需要的.
知道如何实现这样的目标吗?我应该使用结构进行部分特化然后使用辅助函数吗?
你不需要那么冗长;您可以启用另一个 foo
,方法如下:
template<typename T>
auto foo(T&& v) -> decltype(v.log(), void())
{
v.log();
}
这叫做trailing return type. You provide the decltype
to evaluate the expressions (1. v.log()
, 2. void()
) with comma operator分离。如果第一个表达式(即 v.log()
)失败,则重载不适合调用。因此,它适用于另一个 foo
。否则,它接受带有 void
return 的重载,这是从 void()
表达式求值的!
你走的很好,但是,转发参考,
decltype(&T::log)
变为 decltype(&(Y&)::log)
无效。
使用 std::decay
解决了您的问题:
template<typename T,
std::enable_if_t<
std::is_member_function_pointer_v<decltype(&std::decay_t<T>::log)>,
int> = 0>
void foo(T&& v)
{
v.log();
}