C++ 在可变模板中使用lambdas调用std::make_tuple-这在C++;11?

C++ 在可变模板中使用lambdas调用std::make_tuple-这在C++;11?,c++,c++11,tuples,variadic-templates,lambda,C++,C++11,Tuples,Variadic Templates,Lambda,在C++11中,lambda函数是一个对象,应该可以用它调用make_tuple,对吗 void foobar() { auto t = std::make_tuple([](){ std::make_shared<int>(); }); } void foobar(){ auto t=std::make_元组([](){std::make_shared();}); } 这个代码对我有用 现在,如果我们添加可变模板,会发生什么情况: #include <tuple&

在C++11中,lambda函数是一个对象,应该可以用它调用make_tuple,对吗

void foobar() {
    auto t = std::make_tuple([](){ std::make_shared<int>(); });
}
void foobar(){
auto t=std::make_元组([](){std::make_shared();});
}
这个代码对我有用

现在,如果我们添加可变模板,会发生什么情况:

#include <tuple>
#include <memory>

template <class... T>
void foobar() {
    auto t = std::make_tuple([](){ std::make_shared<T>(); }...);
}

int main(int, char**)
{
    foobar<int, float, double>();
    return 0;
}
#包括
#包括
模板
void foobar(){
auto t=std::make_tuple([](){std::make_shared();};
}
int main(int,char**)
{
foobar();
返回0;
}
这一个未能在GCC 4.7.2中编译

main.cpp: In lambda function:
main.cpp:6:54: error: parameter packs not expanded with '...':
main.cpp:6:54: note:         'T'
main.cpp: In function 'void foobar()':
main.cpp:6:57: error: expansion pattern '#'lambda_expr' not supported by dump_expr#<expression error>' contains no argument packs
main.cpp: In instantiation of 'void foobar() [with T = {int, float, double}]':
main.cpp:11:29:   required from here
main.cpp:在lambda函数中:
main.cpp:6:54:错误:参数包未扩展为“…”:
main.cpp:6:54:注:“T”
main.cpp:在函数“void foobar()”中:
main.cpp:6:57:错误:dump#u expr#不支持扩展模式“#”lambda_expr”不包含参数包
main.cpp:在“void foobar()[with T={int,float,double}]的实例化中:
main.cpp:11:29:从这里开始需要
我想知道,按照标准,这个代码正确吗?

方法#1: 解决这个问题的简单方法似乎是
std::function

#include <tuple>
#include <memory>

template <class T>
std::function<std::shared_ptr<T>()> make_shared_lambda() {
    return [](){ return std::make_shared<T>(); };
}

template <class... T>
void foobar() {
    auto factories = std::make_tuple(make_shared_lambda<T>()...); 
    auto tracer = std::get<2>(factories)();
}

// demonstration 
#include <cstdio>
struct Tracer { 
    Tracer() { puts("Tracer()");   }
   ~Tracer() { puts("~Tracer()");  } 
};

int main()
{
    foobar<int, float, Tracer>();
}
方法2: 显然,
std::function
的类型擦除存在性能开销。您可以轻松利用以下事实(标准5.1.2/6):

#包括
#包括
模板自动生成共享文件()->std::共享文件(*)()
{
return[](){return std::make_shared();};
}
模板std::tuple foobar(){
返回std::make_tuple(make_shared_f()…);
}
//示范
int main()
{
自动工厂=foobar();
自动双_ptr=std::get(factories)();
}
如果您的编译器支持模板别名,则可以使其不那么神秘:

template <typename T> using shared_factory = std::shared_ptr<T>(*)();

template <class T> shared_factory<T> make_shared_f() {
    return []() { return std::make_shared<T>(); };
}
使用shared_factory=std::shared_ptr(*)的模板;
模板共享\u工厂制作\u共享\u f(){
return[](){return std::make_shared();};
}

这是gcc中的一个已知错误:(最初的示例是一个不同的模式,涵盖了参数包的捕获,但该模式和合并错误背后的问题是gcc根本没有实现lambdas和variadics的交集)


就标准而言,它是完全可以接受的代码。

您的方法2似乎是错误的。OP的
foobar()
构造了一个“空函数的元组,每个都返回
共享的\u ptr
”,但您的构造了一个“空函数,返回默认构造的
共享的\u ptr
(?)”@KennyTM您似乎是对的。让我重写第二个:)我添加了一个更好的解决方法,而没有使用
std::function
#include <tuple>
#include <memory>

template <class T> auto make_shared_f() -> std::shared_ptr<T>(*)() 
{
    return []() { return std::make_shared<T>(); };
}

template <class... T> std::tuple<std::shared_ptr<T>(*)()...> foobar() {
    return std::make_tuple(make_shared_f<T>()...);
}

// demonstration 
int main()
{
    auto factories = foobar<int, float, double>();
    auto double_ptr = std::get<2>(factories)();
}
template <typename T> using shared_factory = std::shared_ptr<T>(*)();

template <class T> shared_factory<T> make_shared_f() {
    return []() { return std::make_shared<T>(); };
}