简体   繁体   English

C ++ 14 auto lambda可以接受Obj <std::tuple<void> &gt; - 但模板功能不能?

[英]C++14 auto lambda can accept Obj<std::tuple<void> > — but template functions cannot?

Below is a program that completely demonstrates the problem I'm seeing. 下面是一个程序,完全展示了我所看到的问题。

First, I start with an object that is defined using a grouping of other types, I started using a std::tuple<> to manage the grouping. 首先,我从一个使用其他类型的分组定义的对象开始,我开始使用std :: tuple <>来管理分组。

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

I am intending these objects to be capable of having the type void scattered in the "pack". 打算这些对象能够在“pack”中散布类型void I am already aware of being unable to "instantiate" a tuple of this type (see Void type in std::tuple ) 我已经意识到无法“实例化”这种类型的元组(请参阅std :: tuple中的Void类型

I want to pass these objects around, perhaps copy/move them... none of their data members are a tuple of these types. 我想传递这些对象,也许复制/移动它们......它们的数据成员都不是这些类型的元组。 In fact, I can reproduce the problem using the empty object definition above. 事实上,我可以使用上面的空对象定义重现问题。

I can make it work, using something like: 可以使用以下内容使其工作:

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

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

These types of "grouping" structs are used frequenly in variadic recursion, and they are meant to never get created/used. 这些类型的“分组”结构在可变递归中经常使用,并且它们意味着永远不会被创建/使用。 Just to group template args. 只是为了分组模板args。

However, I "want" the signature of the 'object' to be made up of "user expected" types/names. 但是,我“希望”“对象”的签名由“用户期望的”类型/名称组成。

Basically, I was experimenting with any possible way of passing one of these objects around when std::tuple is used to "group", and could only find one way: auto lambdas. 基本上,当std::tuple用于“分组”时,我正在尝试传递其中一个对象的可能方法,并且只能找到一种方法:auto lambdas。

Can anybody explain: 谁能解释一下:

  1. why the "auto" lambda's can work for this? 为什么“汽车”lambda可以为此工作?

    something about delayed template deduction? 关于延迟模板演绎的事情? like the diff b/w "auto" and "decltype(auto)"? 比如diff b / w“auto”和“decltype(auto)”?

  2. how to "design" a function parameter to accept one of these objects. 如何“设计”一个函数参数来接受其中一个对象。

-- thanks to you all for any insights on this oddity - 感谢大家对这种奇怪的见解

Example: 例:

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

Edit : adding a trimmed down reproduction: 编辑 :添加精简复制:

#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> is an associated class of object<std::tuple<void>> , and so in an unqualified call in which argument-dependent lookup is performed, std::tuple<void> is instantiated to look for any friend functions that might have been defined inline. std::tuple<void>object<std::tuple<void>>关联类 ,因此在执行与参数相关的查找的非限定调用中, std::tuple<void>被实例化以查找任何可能已内联定义的friend函数。 This instantiation causes an error. 此实例化会导致错误。

Argument-dependent lookup is not performed if the thing being called doesn't name a function or function template; 如果被调用的东西没有命名函数或函数模板,则不执行依赖于参数的查找; hence using a lambda works - takeobj_lambda is an object. 因此使用lambda作品 - takeobj_lambda是一个对象。

If you use either a qualified call ( ::takeobj(oval) ), or parenthesize takeobj ( (takeobj)(oval) ), then the code compiles. 如果使用限定调用( ::takeobj(oval) )或parenthesize takeobj(takeobj)(oval) ),则代码编译。 Both of these disable ADL. 这两个都禁用ADL。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在 lambda C++14 中捕获 std::promise - Capture std::promise in a lambda C++14 C++14 中的递归 lambda 函数 - Recursive lambda functions in C++14 在C ++ 14中使用通用Lambda函数进行递归 - Recursion with generic lambda functions in C++14 错误:在 lambda 参数声明中使用 &#39;auto&#39; 仅适用于 &#39;-std=c++14&#39; 或 &#39;-std=gnu++14&#39; 和 PCL 错误 - error: use of ‘auto’ in lambda parameter declaration only available with ‘-std=c++14’ or ‘-std=gnu++14’ and PCL errors 为什么我不能在C ++ 14中移动lambda中的std :: unique_ptr? - Why can't I move the std::unique_ptr inside lambda in C++14? 使用C ++ 14索引序列可以改进元组的可变参数模板递归吗? - Can tuple variadic template recursion be improved with C++14 index sequences? C++14:具有泛型 std::function 作为类成员的泛型 lambda - C++14: Generic lambda with generic std::function as class member C ++ 14中通用Lambda中的静态自动变量 - Static Auto Variable in Generic Lambda in C++14 为什么 `constexpr` 是`std::max()` 的 C++14 模板原型的一部分? - Why is `constexpr` part of the C++14 template prototype for `std::max()`? 使用 C++14 lambda 测量任意函数的执行时间 - Measure execution time of arbitrary functions with C++14 lambda
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM