【问题标题】:Do template structs need std::decay when using forwarding references in C++17?在 C++17 中使用转发引用时,模板结构是否需要 std::decay?
【发布时间】:2016-08-25 15:23:20
【问题描述】:

在 C++17 中,可以使用instantiate objects without specifying the template types。基本上,这段代码可以编译:

std::pair p(2, 4.5);     // deduces to std::pair<int, double> p(2, 4.5);
std::tuple t(4, 3, 2.5); // same as auto t = std::make_tuple(4, 3, 2.5);

所以,假设以下代码:

template<typename... Ts>
struct Foo
{
    Foo(Ts&&... ts) :
        ts{std::forward_as_tuple(ts...)}
    {}

    std::tuple<Ts...> ts;
};

int main()
{
    auto f = [] { return 42; };
    Foo foo{f, [] { return 84; }};
}

我应该在这样的元组声明中使用std::decay吗?

std::tuple<std::decay_t<Ts>...> ts;

因为这就是我编写函数以根据推导出的模板类型返回对象的方式:

template<typename T>
auto make_baz(T&& t) -> baz<std::decay_t<T>>;

我可以在 Foo 的构造函数中看到这种模式,它使用转发引用将值正确地传递给元组。我不确定这里的类型推导是否表现相同。

【问题讨论】:

  • 为什么不加个扣分指南?
  • @cpplearner Foo 的实例化已经有类型推导。我看不出演绎指南有什么好处,还是我遗漏了什么?

标签: c++ c++17 template-argument-deduction forwarding-reference


【解决方案1】:

无需更改类的内部结构即可使其与类模板参数推导一起使用;这就是演绎指南的用途。

最好的起点是编写一个make_X 函数;无论您是否提供,决定所需的签名都会让您知道您是否需要编写显式演绎指南,或者可以依赖从构造函数推断出的隐式演绎指南。

事实上,演绎指南,无论是隐式还是显式,都与make_X 函数的行为相同(直到复制构造函数省略)。

您想要的makeFoo 将具有以下声明:

template<typename... Ts>
auto makeFoo(Ts&&... ts) -> Foo<std::decay_t<Ts>...>;

由于这会对模板参数进行转换,因此您需要提供明确的推导指南;这在语法上与 makeFoo 的声明相同,只是删除了 auto make

template<typename... Ts>
Foo(Ts&&... ts) -> Foo<std::decay_t<Ts>...>;

如果您不提供显式推导指南,则会从您的构造函数生成一个,除了模板参数推导期间发生的类型转换之外,不会进行任何类型转换:

template<typename... Ts>
Foo(Ts&&... ts) -> Foo<Ts...>;

这不是你想要的,因为它不适用于std::decay_t。修改类的内部结构(将std::decay_t 添加到ts)会起作用,但是当明确的推导指南解决问题时,就没有必要了。

【讨论】:

  • 假设对象声明会发生类型推导,这样做有什么好处?
  • 抱歉,“那个”是什么意思?你的意思是decay_t,还是别的什么?
  • 演绎指南。在 C++17 中,这将发生在 Foo 实例化中,因此您无需指定任何类型。抱歉,如果我的问题不清楚:如果我将左值传递给构造函数,我想知道 Foo 中 T 的类型推导是否会成为引用。我将编辑我的问题。
  • @thlst 已更新。您肯定需要一个明确的推导指南,因为您正在对模板参数执行转换。您希望Foo 可以正常使用,对吧?
  • Foo(Ts&amp;&amp;... ts) -&gt; Foo&lt;std::decay_t&lt;Ts&gt;...&gt;; 这是 C++1z 中的有效语法吗?你是说Foo&lt;std::decay_t&lt;Ts&gt;...&gt; Foo(Ts&amp;&amp;... ts) 吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多