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

C++14 auto lambda can accept Obj<std::tuple<void> > -- but template functions cannot?

本文关键字:lt gt 不能 函数 void std lambda 自动 C++14 Obj tuple      更新时间:2023-10-16

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

首先,我

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

template <typename> class object;
template <typename... Rs> class object<std::tuple<Rs...> > {
};

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

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

我可以让它工作,使用如下内容:

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

这些类型的"分组"结构在可变参数递归中经常使用,并且它们永远不会被创建/使用。 只是为了对模板参数进行分组。

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

基本上,当std::tuple用于"分组"时,我正在尝试任何可能的方式传递这些对象之一,并且只能找到一种方法:自动 lambdas。

谁能解释一下:

  1. 为什么"自动"λ可以为此工作?

    关于延迟模板扣除? 喜欢差异黑白"自动"和"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 messagen";
    }
};

// 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;
}

编辑:添加修剪后的复制品:

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

std::tuple<void>object<std::tuple<void>>的关联类,因此在执行参数相关查找的非限定调用中,std::tuple<void>被实例化以查找可能已内联定义的任何friend函数。此实例化会导致错误。

如果被调用的事物未命名函数或函数模板,则不执行依赖于参数的查找;因此使用 lambda 有效 - takeobj_lambda是一个对象。

如果使用限定调用 ( ::takeobj(oval) ) 或括号takeobj(takeobj)(oval) ),则代码将编译。这两者都会禁用 ADL。