提问人:Jr_vv 提问时间:11/23/2022 最后编辑:Jr_vv 更新时间:11/23/2022 访问量:58
如何使用两个模板参数重载类方法,以便我可以将 std::function 用作其中之一?
How to overload class method with two template parameters, so I can use std::function as one of them?
问:
我需要一些有关使用模板的帮助。 我有这样的代码, 它是包含两个 std::function 对象向量的类,以及一个在其中一个中推送某些函数(bind、lambda 或 functor)的方法:
typedef std::function<int(int)> unFuncPtr;
typedef std::function<int(int, int)> binFuncPtr;
class Operations
{
public:
template <size_t argsCount, class T>
void RegisterOperator(T fn) {
if (argsCount == 1) {
m_unaryOperations.push_back(fn);
}
if (argsCount == 2) {
m_binaryOperations.push_back(fn);
}
}
private:
std::vector<unFuncPtr> m_binaryOperations;
std::vector<binFuncPtr> m_unaryOperations;
例如,我希望这段代码将带有两个参数的 lambda 推送到调用方法,如下所示:m_binaryOperations
m_unaryOperations
RegisterOperator
Operations operations;
operations.RegisterOperator<1>([](int x) {return x * x; })
operations.RegisterOperator<2>([](int x, int y) {return x + y; })
但它给了我一个功能式的投射错误。
据我了解,这是因为在一个函数中以两种不同的方式进行解释。class T
如何修改代码以使用模板参数 1 或 2 调用方法,以便知道参数是什么类型以及必须将参数中的向量函数推送到什么?argsCount
class T
我尝试了不同的方法来解决这个问题。
第一个是在类中重载模板,如下所示:
template <size_t argsCount, class T>
void RegisterOperator(T fn) {
}
template<>
void RegisterOperator<1>(unFunPtr fn) {
m_unaryOperations.push_back(fn);
}
template<>
void RegisterOperator<2>(binFunPtr fn) {
m_binaryOperations.push_back(fn);
}
但是调试告诉我,它甚至不会进入我上面写的示例的重载函数。
第二个是重载类中的模板,如下所示:
template<class T = unFunPtr>
void RegisterOperator<1>(T fn) {
m_unaryOperations.push_back(fn);
}
template<class T = binFunPtr>
void RegisterOperator<2>(T fn) {
m_binaryOperations.push_back(fn);
}
我认为默认模板允许我在调用方法时只在模板中定义,但它会导致很多错误。argsCount
希望得到你的帮助。
答:
2赞
Daniel Langr
11/23/2022
#1
首先,你在这里有一个错别字:
std::vector<unFuncPtr> m_binaryOperations;
std::vector<binFuncPtr> m_unaryOperations;
它应该是:
std::vector<unFuncPtr> m_unaryOperations;
std::vector<binFuncPtr> m_binaryOperations;
其次,即使那样它也不会编译,因为对于“普通”,两个分支都需要可编译。如果您有可用的 C++17,则可以解决问题:if
if constexpr
void RegisterOperator(T fn) {
if constexpr (argsCount == 1)
m_unaryOperations.push_back(fn);
if constexpr (argsCount == 2)
m_binaryOperations.push_back(fn);
}
现场演示:https://godbolt.org/z/bbqs7Knbd
评论
0赞
Jr_vv
11/24/2022
多谢!!它有效。但是带有覆盖模板的代码版本呢,为什么它不起作用?
0赞
Daniel Langr
11/25/2022
@Jr_vv 这不是超载(也不是超载),而是专业化。AFAIK,则不能在类范围内专用化成员函数模板。有关详细信息,请参阅 stackoverflow.com/q/51767514/580083。
评论
if constexpr(requires(){ m_unaryOperations.push_back(fn); }
size_t argsCount