2017-07-06 167 views
15

我有一个模板功能,我们称之为“客户”:如何使用不同数量的默认参数来包装函数以使其只有一个参数?

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) {} 

上述功能是给定的。现在我想要做的是将它们作为第一个参数传递给上面的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<>()

我想要做的是自动包装或有一个(模板)包装,而不是每个适配器。我觉得这可能是variadics的情况,但几乎没有关于如何正确应用它们的想法。

C++ 11很好,如果绝对必要的话,C++ 14是很好的。

+0

是否允许使用lambda? – AndyG

+0

@AndyG它位于任何类之外的命名空间中,所以我认为是的,只要有一个理智的地方来保存它们。 – iksemyonov

+1

@rici因为[不起作用](https://wandbox.org/permlink/WYzQfhLbPA7KXIEy)。 – Barry

回答

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

“加号”不是拼写错误吗?我以前从来没有见过。 – iksemyonov

+6

@iksemyonov这是一个[正面lambda](https://stackoverflow.com/questions/18889028/a-positive-lambda-what-sorcery-is-this):)只是开玩笑,它是用来将lambda转换成函数指针借助于其转换运算符(请参阅链接问题)。 – Rakete1111

+0

谢谢!天啊。很高兴我发布了这个问题 - 将永远不会知道。 – iksemyonov

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的宏)来内联。

+0

'decltype(auto)'不能作为返回类型吗? –

+0

谢谢!模板解决方案包含一些我必须查找的内容,但不管它看起来相当可怕。没有办法或需要在这里使用可变参数来解释参数的不同数量? – iksemyonov

+0

@iksemyonov你说你只想传递'std :: string',你需要什么“不同数量的参数”? –

0

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

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

与lambda表达式相比,这可能会更自我记录一些。

谁知道,当它从一个文件读取和写入参数的时候,那么包装类就是完成这个任务的理想场所。

相关问题