【问题标题】:Will template parameter deduction for constructors available since C++17 allow explicitly specify some of the class template arguments?自 C++17 以来可用的构造函数的模板参数推导是否允许显式指定一些类模板参数?
【发布时间】:2016-08-21 18:13:21
【问题描述】:

除了构造函数模板参数推导最明显的用法,我可以想象一些更复杂的用例,我们只推导模板类的部分参数,例如:

std::pair<int> p(1, 2); // std::pair<int, int>

虽然这种构造是在函数中扣除模板参数的自然结果,但我找不到任何这种用法的例子。 也许是因为带有可变模板参数的类的歧义?

std::tuple<int> t(1, 2, 3); // std::tuple<int, int, int>

但是,这种引入语法的方式并不能替代我们可以使用功能的太好的“make_*”包装器(参见N3602)......

【问题讨论】:

    标签: c++ templates language-lawyer c++17


    【解决方案1】:

    显然不是。 P0091 的介绍声称确实如此,但实际的措辞却完全不同:

    对应于类模板的模板名称,后跟一个带括号的表达式列表...

    这排除了使用模板名称 + 一些参数和“带括号的表达式列表”。在措辞的其他部分也从语法上排除了它。

    所以不,不可能指定一些参数同时推断其他参数。

    【讨论】:

    • @W.F.:提案的版本错误。这个网站有all of the papers, grouped by year
    • 实际上,它是不允许的 - 它从实际措辞中删除,很大程度上是由于“std::tuple&lt;int&gt; t(1, 2, 3);”问题。作者只是未能更新介绍性部分。
    • @T.C.哦,太糟糕了...我担心std::tuple&lt;int&gt; t(1, 2, 3); 可能是一个极端情况...
    • @W.F.:我已经更新了答案以反映 TC 指出的内容。
    • 有时我希望能够说“这个函数参数包必须是全推导的或全显式指定的”。这样,std::tuple 构造函数可以定义为tuple(T &amp;&amp; protected ...)(bikeshedding),然后std::tuple&lt;int&gt; 的三个参数将不匹配,而不是扩展T
    【解决方案2】:

    是的,但是是间接的。

    对于其他有类似问题但想要有效解决方法的人,而不是语言律师:

    这可能是一个深奥的例子,但它实际上与该技术的实际应用非常接近。

    您使用 C++17 中的演绎指南和接受辅助类型的附加构造函数。当你有一个包含许多模板参数的类时,这通常会更容易。

    https://en.cppreference.com/w/cpp/language/class_template_argument_deduction

    template <std::size_t v>
    struct SizeT{};
    
    template <std::size_t v, typename T>
    struct PrintToBuffer
    {
        T const Dunno;
    
        PrintToBuffer(T const & pInput) : 
            Dunno(pInput)
        {}
        //This works for any class, as it just forwards to another constructor
        template <typename ... Args>
        PrintToBuffer(SizeT<v>, Args && ... pInput) : 
            PrintToBuffer(std::forward<Args>(pInput)...) 
        {}
    
        void Print(std::array<char, v> & pOutput)
        {
            for (auto & c : pOutput)
                c = Dunno;
        }
    };
    

    这可以在这里玩:

    https://godbolt.org/z/E8d1Dt

    编辑,为元组添加示例

    以元组为例:

    template <typename ... Args>
    struct Types{};
    
    template <typename ... T>
    struct Tuple : std::tuple<T...>
    {
        using base_t = std::tuple<T...>;
        using base_t::base_t;
    
        template <typename ... Ignore>
        Tuple(Types<Ignore...>, T && ... pInput) : base_t(std::forward<T>(pInput)...) {}
    };
    
    template <typename ... Defined, typename ... Args>
    Tuple(Types<Defined...>, Defined && ..., Args&& ...) -> Tuple<Defined..., Args...>;
    

    在此处使用编译器资源管理器,请注意推导和定义的模板参数均已正确构造:

    https://godbolt.org/z/VrT9Lf

    用法:

    auto my_tuple = Tuple(Types&lt;int, short&gt;{}, 1, 1, 'a');

    【讨论】:

      猜你喜欢
      • 2011-02-21
      • 1970-01-01
      • 2013-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多