我无法从std::tuple
兼容类型中逐个元素地初始化std::tuple
个元素。为什么它不像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
overloads no. 4 and 5完全是出于这个目的:
template <class... UTypes>
tuple(const tuple<UTypes...>& other);
template <class... UTypes>
tuple(tuple<UTypes...>&& other);
注意:
除非所有
std::is_constructible<Ti, const Ui&>::value
的{{1}}为true
,否则不参与重载决策。
i
是std::is_constructible<Foo<int>, int>::value
。从GCC模板错误,我可以看到超载没有。 3:
true
而是选择。为什么呢?
答案 0 :(得分:3)
当传递tuple&
时,重载(4)和(5)是比(3)更差的匹配:它们是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)) {}
然而,右值情况应该有效或不明确。查看实时示例的错误日志,我看到的唯一错误是左值。