C++ 14 auto lambda可以接受Obj <std :: tuple <void >> - 但模板函数不能?

Cra*_*Neb 5 c++ lambda templates tuples auto

下面是一个程序,完全展示了我所看到的问题.

首先,我从一个使用其他类型的分组定义的对象开始,我开始使用std :: tuple <>来管理分组.

template <typename> class object;
template <typename... Rs> class object<std::tuple<Rs...> > {
};
Run Code Online (Sandbox Code Playgroud)

打算这些对象能够将类型void分散在"包"中.我已经意识到无法"实例化"这种类型的元组(请参阅std :: tuple中的Void类型)

我想传递这些对象,也许复制/移动它们......它们的数据成员都不是这些类型的元组.事实上,我可以使用上面的空对象定义重现问题.

可以使用以下内容使其工作:

template <typename... Rs> struct TGrp {};

template <typename> class object;
template <typename... Rs> class object<TGrp<Rs...> > {
};
Run Code Online (Sandbox Code Playgroud)

这些类型的"分组"结构在可变递归中经常使用,并且它们意味着永远不会被创建/使用.只是为了分组模板args.

但是,我"希望""对象"的签名由"用户期望的"类型/名称组成.

基本上,当我习惯于"分组" 时,我正在尝试传递其中一个对象的任何可能的方法std::tuple,并且只能找到一种方法:自动lambdas.

谁能解释一下:

  1. 为什么"汽车"lambda可以为此工作?

    关于延迟模板演绎的事情?比如diff b/w"auto"和"decltype(auto)"?

  2. 如何"设计"一个函数参数来接受其中一个对象.

- 感谢大家对这种奇怪的见解

例:

#include <tuple>
#include <iostream>

#define GRP std::tuple      // IF 'tuple' used:  compile error where noted below
//#define GRP TGrp          // if THIS is used:  all works, and TGrp() is never constructed


// Grouping mechanism
template <typename... Ts> struct TGrp {
    TGrp() {
        std::cout << "Never printed message\n";
    }
};


// MAIN OBJECT (empty for forum question)
template <typename> class object;
template <typename... Rs> class object<GRP<Rs...> > {
};



// Regular function                  (does NOT work)
void takeobj(object<GRP<void> >& obj) { (void)obj; }

// Lambda - taking anything...       (only thing I could make WORK)
auto takeobj_lambda = [](auto obj) { (void)obj; };

// Template func - taking anything   (does NOT work)
template <typename T> void takeobj_templ_norm(T obj) { (void)obj; }
template <typename T> void takeobj_templ_clref(const T& obj) { (void)obj; }
template <typename T> void takeobj_templ_lref(T& obj) { (void)obj; }
template <typename T> void takeobj_templ_rref(T&& obj) { (void)obj; }


int main()
{
    object<GRP<void> > oval;

    //takeobj(oval);                  // <--    causes compile error

    takeobj_lambda(oval); // works

    //takeobj_templ_norm(oval);       // <--    also error
    //takeobj_templ_clref(oval);      // <--    also error
    //takeobj_templ_lref(oval);       // <--    also error
    //takeobj_templ_rref(oval);       // <--    also error
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

编辑:添加精简复制:

#include <tuple>


// MAIN OBJECT (empty for forum question)
template <typename> class object;
template <typename... Rs> class object<std::tuple<Rs...> > {
};

// Regular function                  (does NOT work)
void takeobj(object<std::tuple<void> >& obj) { (void)obj; }

// Lambda - taking anything...       (only thing I could make WORK)
auto takeobj_lambda = [](auto obj) { (void)obj; };


int main()
{
    object<std::tuple<void> > oval;

    //takeobj(oval);                  // <--    causes compile error
    takeobj_lambda(oval); // works

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 6

std::tuple<void>是一个关联类object<std::tuple<void>>,因此,在其中进行参数相关的查找不合格的呼叫,std::tuple<void>被实例化,以寻找任何friend可能已内嵌定义的函数.此实例化会导致错误.

如果被调用的东西没有命名函数或函数模板,则不执行依赖于参数的查找; 因此使用lambda作品 - takeobj_lambda是一个对象.

如果您使用限定的call(::takeobj(oval))或parenthesize takeobj((takeobj)(oval)),则代码将进行编译.这两个都禁用ADL.