为什么不能用兼容类型的std :: tuple来按元素构造std :: tuple? [英] Why can't std::tuple be element-wise constructed with a std::tuple of compatible types?

查看:143
本文介绍了为什么不能用兼容类型的std :: tuple来按元素构造std :: tuple?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法从兼容类型的std::tuple逐元素初始化std::tuple元素.为什么它不能与boost::tuple一起使用?

I can't initialize std::tuple elements element-wise from a std::tuple of compatible types. Why doesn't it work as with boost::tuple?

#include <tuple>
#include <boost/tuple/tuple.hpp>

template <typename T>
struct Foo
{
    // error: cannot convert 'std::tuple<int>' to 'int' in initialization
    template <typename U>
    Foo(U &&u) : val(std::forward<U>(u)) {}

    T val;
};

int main()
{
    boost::tuple<Foo<int>>{boost::tuple<int>{}};    // ok

    auto a = boost::tuple<int>{};
    boost::tuple<Foo<int>>{a};                      // ok

    std::tuple<Foo<int>>{std::tuple<int>{}};        // fails with rvalue

    auto b = std::tuple<int>{};
    std::tuple<Foo<int>>{b};                        // fails with lvalue
}

在Coliru上生活 (GCC或Clang和libstdc ++无法编译,但是 Clang和libc ++编译没有错误)

std::tuple没有进行元素构造,它实例化了Foo<int>::Foo<std::tuple<int>>而不是Foo<int>::Foo<int>.我以为 std::tuple::tuple不超载. 4和5 正是出于这个目的:

std::tuple is not doing element-wise construction and it instantiates Foo<int>::Foo<std::tuple<int>> instead of Foo<int>::Foo<int>. I thought std::tuple::tuple overloads no. 4 and 5 were exactly for that purpose:

template <class... UTypes>
tuple(const tuple<UTypes...>& other);

template <class... UTypes>
tuple(tuple<UTypes...>&& other);

注意:

除非所有i
std::is_constructible<Ti, const Ui&>::valuetrue,否则不参与重载解析.

Does not participate in overload resolution unless
std::is_constructible<Ti, const Ui&>::value is true for all i.

std::is_constructible<Foo<int>, int>::valuetrue.从GCC模板错误中,我可以看到没有过载. 3:

std::is_constructible<Foo<int>, int>::value is true. From the GCC template error, I can see that overload no. 3:

template <class... UTypes>
explicit tuple(UTypes&&... args);

而是选择

.为什么?

is selected instead. Why?

推荐答案

在传递tuple&时,重载(4)和(5)比(3)更差:它们是const&&&重载,而(3)通过完美转发的魔力完全匹配.

Overloads (4) and (5) are poorer matches than (3) when passed a tuple& : they are const& and && overloads, while (3) matches exactly through the magic of perfect forwarding.

(3)有效,因为您的Foo(U&&)构造函数过于贪婪.

(3) is valid because your Foo(U&&) constructor is overly greedy.

将SFINAE检查添加到Foo(U&&),以便在构建失败时不匹配:

Add SFINAE checks to Foo(U&&) so that it fails to match when it fails to build:

template <class U,
  std::enable_if_t<std::is_convertible<U,int>{},int>* =nullptr
>
Foo(U &&u) : val(std::forward<U>(u)) {}

但是,右值情况应该起作用或模棱两可.查看您的实时示例的错误日志,我看到的唯一错误是左值一个.

The rvalue case should, however, work or be ambiguous. Looking at the error log of your live example, the only error I see is with the lvalue one.

这篇关于为什么不能用兼容类型的std :: tuple来按元素构造std :: tuple?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆