12

我无法从兼容类型中std::tuple逐元素初始化元素。std::tuple为什么它不能像 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
}

Live on Coliru(GCC 或 Clang 和 libstdc++ 无法编译,但是Clang 和 libc++ 编译没有错误


std::tuple没有进行元素构造,它实例化Foo<int>::Foo<std::tuple<int>>而不是Foo<int>::Foo<int>. 我认为std::tuple::tuple超载没有。4 和 5正是为此目的:

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

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

笔记:

不参与重载决议,除非
std::is_constructible<Ti, const Ui&>::valuetruefor all i

std::is_constructible<Foo<int>, int>::valuetrue。从 GCC 模板错误中,我可以看到重载号。3:

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

而是选择。为什么?

4

1 回答 1

3

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

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

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

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

然而,右值的情况应该是有效的或者是模棱两可的。查看您的实时示例的错误日志,我看到的唯一错误是左值错误。

于 2016-07-09T13:23:32.687 回答