【问题标题】:Difference between references and values in deduction guides扣除指南中的参考值和值之间的差异
【发布时间】:2018-07-08 18:41:51
【问题描述】:

考虑类型A

template <typename T, size_t N>
struct A
{
    T arr[N];
};

C++17用户自定义deduction guides有什么区别

template <typename T, typename ... Ts>
A(const T&, const Ts& ...) -> A<T, 1 + sizeof...(Ts)>;

template <typename T, typename ... Ts>
A(T, Ts ...) -> A<T, 1 + sizeof...(Ts)>;

?

或者,换句话说,const 引用和演绎指南中的值有什么区别?


请注意,问题不是关于模板函数类型推导,而是关于新的 C++17 特性,类模板参数推导的用户定义推导指南,因此您可以简单地声明 A instance{1,2,3} 而不是 A&lt;int, 3&gt; instance{1,2,3} .

【问题讨论】:

    标签: c++ language-lawyer c++17 variadic-templates template-argument-deduction


    【解决方案1】:

    或者,换句话说,const 引用和演绎指南中的值有什么区别?

    在你的情况下可能不是,但一般来说,是的。

    T 不可复制时。

    在下面的例子中,第一种情况(常量引用)编译接收std::unique_ptr&lt;int&gt;,第二种情况(值)给出错误

    #include <iostream>
    #include <memory>
    
    template <typename T, size_t N>
    struct A
     { template <typename ... Ts> A (Ts const & ...) {} };
    
    template <typename T, size_t N>
    struct B
     { template <typename ... Ts> B (Ts const & ...) {} };
    
    template <typename T, typename ... Ts>
    A(T const &, Ts const & ...) -> A<T, 1U + sizeof...(Ts)>;
    
    template <typename T, typename ... Ts>
    B(T, Ts ...) -> B<T, 1 + sizeof...(Ts)>;
    
    
    int main()
     {
       std::unique_ptr<int> up;
    
       auto a = A{up};    // compile
       // auto b = B{up}; // doesn't compile
     }
    

    【讨论】:

    • 有趣。没有想到这一点。由于构造函数没问题(引用),我认为没有问题。很好的收获。
    • @bolov - 工作也是B构造函数复制;但不适用于问题中的A(因为数组arr 的初始化需要副本)
    • auto b = B{up}; 编译 under Clang
    • [over.best.ics]/2: "其他属性,如生命周期、存储类、对齐方式、参数的可访问性、参数是否为位域、函数是否被删除,都被忽略了。"
    • @xskxzr - 我不是标准的大师,但我不认为你引用的片段说auto b = B{up}; 是可以的;遵循(我正在阅读 C++17 标准,所以 16.3.3.1.2)“因此,尽管可以为给定的参数-参数对定义隐式转换序列,但从参数到参数的转换可能仍然有问题——归根结底形成”。我想是这样的:选择了一个已删除的函数(std::unique_ptr 的复制构造函数,因此代码“归根结底是错误的”。但我再说一遍:我不是专家,所以我会准备C++ 大师的另一个问题。
    【解决方案2】:

    不同之处在于,当在推导指南中使用值时,参数会因模板参数推导而衰减。例如,

    #include <cstddef>
    using std::size_t;
    
    template <typename T, size_t N>
    struct A
    {
        T arr[N];
    };
    
    template <typename T, typename ... Ts>
    A(const T&, const Ts& ...) -> A<T, 1 + sizeof...(Ts)>;
    
    template <typename T, size_t N>
    struct B
    {
        T arr[N];
    };
    
    template <typename T, typename ... Ts>
    B(T, Ts ...) -> B<T, 1 + sizeof...(Ts)>;
    
    int main()
    {
        int test[42];
        A instanceA {test}; // deduced to be A<int[42], 1>, error 
        B instanceB {test}; // deduced to be B<int*, 1>, ok but the effect may be unexpected
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-05
      • 2020-03-05
      • 2015-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多