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

时间:2016-01-27 03:45:18

标签: c++ templates lambda tuples auto

以下是一个完全展示我所看到问题的程序。

首先,我从一个使用其他类型的分组定义的对象开始,我开始使用std :: tuple&lt;&gt;管理分组。

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

打算这些对象能够将类型void分散在&#34; pack&#34;中。我已经意识到无法&#34;实例化&#34;这种类型的元组 (见Void type in std::tuple

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

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

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

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

这些类型的&#34;分组&#34;在可变递归中频繁使用结构,它们意味着永远不会被创建/使用。只是为了模板组args。

但是,我想要&#34;对象的签名&#39;由&#34;用户期望&#34;组成类型/名称。

基本上,当std::tuple用于&#34; group&#34;时,我正在尝试使用任何可能的传递其中一个对象的方法,并且只能找到一种方法:汽车lambdas。

任何人都可以解释一下:

  1. 为什么&#34; auto&#34; lambda可以为此工作吗?

    关于延迟模板扣除的事情?比如diff b / w&#34; auto&#34;和&#34; decltype(自动)&#34;?

  2. 如何设计&#34;一个函数参数,用于接受其中一个对象。

  3. - 感谢大家对这种奇怪的任何见解

    示例:

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

    修改:添加精简版:

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

1 个答案:

答案 0 :(得分:6)

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

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

如果您使用合格的电话(::takeobj(oval))或括号takeobj(takeobj)(oval)),则代码会进行编译。这两个都禁用ADL。