是否可以像下面这样在C ++ 14中编写模板函数
这里是样本https://godbolt.org/z/9gRk-t
// pseudo code
#include <type_traits>
template <typename T, typename R, typename... Args>
decltype(auto) Call(T& obj, R(T::*mf)(Args...), Args&&... args)
{
return (obj.*mf)(std::forward<Args>(args)...);
}
所以,对于一个测试班
struct Test
{
int Func(){return 1;};
bool Func(bool){return true;}; // overload
void FuncInt(int){};
};
下面的用例的模板模型工作(但失败)
int main()
{
Test test;
// for overload case
auto a = Call<int()>(test, &Test::Func);
auto b = Call<bool(bool)>(test, &Test::Func, true);
// for non-overload case
Call(test, &Test::FuncInt, 1);
return 0;
}
提供错误信息。
#1 with x64 msvc v19.24
example.cpp
<source>(23): error C2672: 'Call': no matching overloaded function found
<source>(23): error C2770: invalid explicit template argument(s) for 'decltype(auto) Call(T &,R (__cdecl T::* )(Args...),Args &&...)'
<source>(5): note: see declaration of 'Call'
<source>(24): error C2672: 'Call': no matching overloaded function found
<source>(24): error C2770: invalid explicit template argument(s) for 'decltype(auto) Call(T &,R (__cdecl T::* )(Args...),Args &&...)'
<source>(5): note: see declaration of 'Call'
Compiler returned: 2
我已经知道了。它像std :: men_fn一样安静。
这是下面的代码和示例https://godbolt.org/z/NoWPV_
#include <type_traits>
template<typename T>
struct Proxy
{
template<typename R, typename ...Args>
decltype(auto) Call(T& obj, R T::*mf, Args&&... args)
{
return (obj.*mf)(std::forward<Args>(args)...);
}
};
struct Test
{
int Func(){return 1;};
bool Func(bool){return true;}; // overload
void FuncInt(int){};
};
int main()
{
Test test;
Proxy<Test> proxy;
// for overload case
auto a = proxy.Call<int()>(test, &Test::Func);
auto b = proxy.Call<bool(bool)>(test, &Test::Func, true);
// for non-overload case
proxy.Call(test, &Test::FuncInt, 1);
return 0;
}
问题与
template <typename T, typename R, typename... Args>
decltype(auto) Call(T& obj, R(T::*mf)(Args...), Args&&... args)
是Args
被推导两次,并且应该相同。
有几种解决此问题的方法:
添加额外的模板参数:
template <typename T, typename R, typename... Args, typename ... Ts>
decltype(auto) Call(T& obj, R(T::*mf)(Args...), Ts&&... args)
{
return (obj.*mf)(std::forward<Ts>(args)...);
}
或使参数不可推论(我使用C ++ 20中的std::type_identity
:]
std::type_identity
或更改完全签名:
template <typename T, typename R, typename... Args>
decltype(auto) Call(T& obj, R(T::*mf)(Args...), std::type_identity_t<Args>... args)
{
return (obj.*mf)(std::forward<Args>(args)...);
}