我无法从兼容类型的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
}
在 Coliru 上实时查看(GCC 或 Clang 和 libstdc++ 无法编译,但是Clang 和 libc++ 可以编译而不出现错误)
std::tuple
没有进行元素级构造,它实例化了 Foo<int>::Foo<std::tuple<int>>
而不是 Foo<int>::Foo<int>
。我认为 std::tuple::tuple
的第四种和第五种重载 就是为此而存在的。template <class... UTypes>
tuple(const tuple<UTypes...>& other);
template <class... UTypes>
tuple(tuple<UTypes...>&& other);
注意:
只有当对于所有的 i,
std::is_constructible<Ti, const Ui&>::value
都为 true 时,才不参与重载决议。
std::is_constructible<Foo<int>, int>::value
的值为 true
。从 GCC 的模板错误中可以看到,重载项 3:
template <class... UTypes>
explicit tuple(UTypes&&... args);
为什么被选择了呢?
-std=libstdc++
选项工作,但可以使用-std=libc++
选项工作。这一定是一个实现问题。 - LogicStuffstoi
)。 - Revolver_Ocelot