提问人:Xin_Wang 提问时间:11/7/2023 更新时间:11/7/2023 访问量:50
模板部分规范
template partial specification
问:
我有以下模板类,就像函数包装器一样:
using MethodId = std::uint16_t;
template <typename Func>
class BaseMethod
{
public:
BaseMethod(const Func &func, std::uint16_t method_id) : _function(func), _method_id(method_id) {}
template <typename... Args>
auto operator()(Args... args) -> decltype(_function(std::forward<Args>(args)...))
{
return _function(std::forward<Args>(args)...);
}
template <typename... Args>
auto invoke(Args... args) -> decltype(_function(std::forward<Args>(args)...))
{
return _function(std::forward<Args>(args)...);
}
private:
Func _function;
MethodId _method_id;
};
使用这个类模板,我可以这样使用:
int adder(int x, int y){return x+y;}
BaseMethod<int(*)(int, int)> foo_tempalte(adder, 0);
但我也想支持这样的用法:
BaseMethod<int, int, int> bar_tempalte(adder, 0);
所以我添加了一个部分规范版本:
template <typename Ret, typename... Args>
class BaseMethod<Ret (*)(Args...)>
{
public:
BaseMethod(Ret (*func)(Args...), std::uint16_t method_id) : _function(func), _method_id(method_id)
{
}
Ret operator()(Args... args)
{
return _function(std::forward<Args>(args)...);
}
Ret invoke(Args... args)
{
return _function(std::forward<Args>(args)...);
}
private:
Ret (*_function)(Args...);
std::uint16_t _method_id;
};
但是当我打电话时BaseMethod<int, int, int> bar_tempalte(adder, 0);
IDE给了我错误:too many arguments for class template "BaseMethod"
我想知道我的代码有什么问题?谢谢!
答:
0赞
Jerry Coffin
11/7/2023
#1
除非你需要支持较旧的编译器(C++17 之前),或者真的,真的,绝对需要强制用户显式传递模板参数,否则我只是让编译器从参数中推断出函数类型:
#include <utility>
#include <cstdint>
#include <iostream>
using MethodId = uint16_t;
template <typename Func>
class BaseMethod
{
public:
BaseMethod(Func func, MethodId method_id) : _function(func), _method_id(method_id) {}
template <typename... Args>
auto operator()(Args... args)
{
return _function(std::forward<Args>(args)...);
}
// leaving out `invoke` since it's basically the same as operator()
private:
Func _function;
MethodId _method_id;
};
int adder(int x, int y){return x+y;}
int add3(int x, int y, int z) { return x + y + z; }
int main() {
// your original code still works:
BaseMethod<int (*)(int, int)> foo_template(adder, 0);
std::cout << foo_template(5, 6) << "\n";
// But it's easier to let the compiler deduce the type:
BaseMethod bar_template(adder, 1);
std::cout << bar_template(1, 2) << "\n";
BaseMethod baz_template(add3, 2);
std::cout << baz_template(1, 2, 3) << "\n";
}
评论
0赞
Xin_Wang
11/8/2023
明白了!感谢您的认真回复:)
评论
<int, int, int>
不匹配。 会调用该专用化,因为它是一个函数指针类型,但只是 3 个类型的参数,与您的任何模板都不匹配。<Ret (*)(Args...)>
BaseMethod<int(*)(int, int)>
BaseMethod<int, int, int>
BaseMethod
BaseMethod<int(*)(int,int)>
BaseMethod<int, int, int>
BaseMethod baz_template(adder, 1);