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

时间:2017-07-06 17:23:20

标签: c++ c++11 templates c++14 default-arguments

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

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

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

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

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

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

void bindAdapteeTwo(const std::string& s) {
    return adaptee_two(s);
}

然后将bindAdapteeX()传递给client<>()

我想做的是自动化包装或者有一个(模板化的)包装器而不是每个适配器一个。我觉得这可能属于变量,但对如何准确应用它们几乎没有想法。

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

3 个答案:

答案 0 :(得分:12)

  

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

C ++ 11解决方案。

  

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

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

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

我不认为将它们包装在模板中或任何可以提供更易读或易于使用的解决方案。

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

#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");
}

答案 1 :(得分:7)

这是宏有帮助的时候之一:

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

虽然你可以写一下内联的主体。

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

void works(std::string const&, int=0);
void fails(std::string const&, int  );

这两个都是void(*)(std::string const&, int)。因此,您无法使用函数模板或类模板包装器 - 您需要使用lambda(或包装lambda的宏)内联。

答案 2 :(得分:0)

我想我会创建一个包装参数的类,让客户端接受该类的实例。这样,您只有一个参数,其中包含您想要的许多参数。

该参数包装器也会提供默认值,并允许您在派生类中针对特定目的对它们进行优化。

与lambdas相比,这可能会更加自我记录。

谁知道,当它从文件中读取和写入参数的时候,那么包装类就是完美的选择。