如何使用不同数量的默认参数包装一个只有一个参数的函数?

iks*_*nov 15 c++ templates default-arguments c++11 c++14

我有一个模板功能,我们称之为"客户端":

template<typename T>
void client(T (*func)(const std::string&), const std::string& s) {}
Run Code Online (Sandbox Code Playgroud)

然后有许多"adaptee"函数都具有相同类型的第一个非默认参数,但以下参数的数量不同并具有默认值:

void adaptee_one(const std::string&, int i = 1, char* c = nullptr) {}
void adaptee_two(const std::string&, float* f = nullptr) {}
Run Code Online (Sandbox Code Playgroud)

以上功能是给定的.现在我想做的是将它们client<>()作为第一个参数传递给上面的函数,我只关心传递第一个参数,const std::string&.所以我做了以下事情:

void bindAdapteeOne(const std::string& s) {
    return adaptee_one(s);
}

void bindAdapteeTwo(const std::string& s) {
    return adaptee_two(s);
}
Run Code Online (Sandbox Code Playgroud)

然后bindAdapteeX()转到client<>().

我想做的是自动化包装或者有一个(模板化的)包装而不是每个适配器.我觉得可变性可能就是这种情况,但对如何准确应用它们几乎一无所知.

C++ 11很好,如果绝对必要,C++ 14就可以了.

sky*_*ack 12

C++ 11很好,如果绝对必要,C++ 14就可以了.

这里是C++ 11解决方案.

我想做的是自动化包装或者有一个(模板化的)包装而不是每个适配器.

我不会这样做.您可以简单地使用非捕获lambdas并让它们衰减到函数指针:

client (+[](const std::string& s) { return adaptee_one(s); }, "foo");
Run Code Online (Sandbox Code Playgroud)

我不认为将它们包装在模板中或其他什么会给你一个更易读或易于使用的解决方案.


作为一个最小的工作示例:

#include<string>

template<typename T>
void client(T (*func)(const std::string&), const std::string& s) {}

void adaptee_one(const std::string&, int i = 1, char* c = nullptr) {}
void adaptee_two(const std::string&, float* f = nullptr) {}

int main() {
    client (+[](const std::string& s) { return adaptee_one(s); }, "foo");
}
Run Code Online (Sandbox Code Playgroud)

  • @iksemyonov这是一个[正面lambda](/sf/ask/1322231991/):)只是开玩笑,它用于将lambda转换为函数指针在其转换运算符的帮助下(参见链接的问题). (6认同)
  • "加"不是拼写错误吗?我以前从未见过这个. (2认同)

Bar*_*rry 7

这是宏有助于的时间之一:

#define WRAP_FN(f) +[](std::string const& s) -> decltype(auto) { return f(s); }
Run Code Online (Sandbox Code Playgroud)

虽然你可以只写内联的主体.


你无能为力.问题是默认参数在函数的签名中不可见,所以一旦进入类型系统,就无法区分:

void works(std::string const&, int=0);
void fails(std::string const&, int  );
Run Code Online (Sandbox Code Playgroud)

这两个都是void(*)(std::string const&, int).所以你不能有一个函数模板或类模板包装器 - 你需要用lambda(或包装lambda的宏)内联它.