空嵌套元组错误

dun*_*ain 6 c++ nested tuples c++11

#include <iostream>
#include <tuple>
int main(){

auto bt=std::make_tuple(std::tuple<>(),std::tuple<std::tuple<>>()); //Line 1
auto bt2=std::make_tuple(std::tuple<>(),std::tuple<>());             //Line 2
}
Run Code Online (Sandbox Code Playgroud)

为什么第1行给出编译错误而第2行编译正常?(在Gcc和Clang中测试过)

有可能的解决方法吗?

clang的错误消息

/usr/include/c++/4.6/tuple:150:50: error: ambiguous conversion from derived class 'std::_Tuple_impl<0, std::tuple<>,
      std::tuple<std::tuple<> > >' to base class 'std::_Head_base<0, std::tuple<>, true>':
    struct std::_Tuple_impl<0, class std::tuple<>, class std::tuple<class std::tuple<> > > -> _Tuple_impl<0UL + 1, class std::tuple<class std::tuple<> > > -> _Head_base<1UL, class std::tuple<class std::tuple<> >, std::is_empty<class tuple<class tuple<> > >::value> -> class std::tuple<class std::tuple<> > -> _Tuple_impl<0, class std::tuple<> > -> _Head_base<0UL, class std::tuple<>, std::is_empty<class tuple<> >::value>
    struct std::_Tuple_impl<0, class std::tuple<>, class std::tuple<class std::tuple<> > > -> _Head_base<0UL, class std::tuple<>, std::is_empty<class tuple<> >::value>
      _Head&            _M_head()       { return _Base::_M_head(); }
                                                 ^~~~~
/usr/include/c++/4.6/tuple:173:33: note: in instantiation of member function 'std::_Tuple_impl<0, std::tuple<>,
      std::tuple<std::tuple<> > >::_M_head' requested here
        _Base(std::forward<_Head>(__in._M_head())) { }
                                       ^
/usr/include/c++/4.6/tuple:334:9: note: in instantiation of member function 'std::_Tuple_impl<0, std::tuple<>,
      std::tuple<std::tuple<> > >::_Tuple_impl' requested here
      : _Inherited(static_cast<_Inherited&&>(__in)) { }
        ^
gcc_bug.cpp:5:10: note: in instantiation of member function
      'std::tuple<std::tuple<>, std::tuple<std::tuple<> > >::tuple' requested here
        auto bt=std::make_tuple(std::tuple<>(),std::tuple<std::tuple<>>());
                ^
1 error generated.
Run Code Online (Sandbox Code Playgroud)

ken*_*ytm 12

看起来你在libstdc ++中发现了一个错误!(此代码与libc ++一起使用).减少测试用例:

#include <tuple>

int main(){
    auto b = std::tuple<std::tuple<std::tuple<>>>{};
}
Run Code Online (Sandbox Code Playgroud)

问题是由于如何std::tuple在libstdc ++中实现.元组实现使用具有多重继承的"递归".你可以认为tuple<X, Y, Z>是继承自Xtuple<Y, Z>.这意味着tuple<tuple<>>将来自继承tuple<>tuple<>,这将导致不明确的基误差.当然真正的问题不是这样,因为tuple<tuple<>>不会产生任何错误.

导致错误的真正实现是这样的:

template<size_t _Idx, typename _Head>
struct _Head_base : public _Head
{};

template<size_t _Idx, typename... _Elements>
struct _Tuple_impl;

template<size_t _Idx>
struct _Tuple_impl<_Idx> {};

template<size_t _Idx, typename _Head, typename... _Tail>
struct _Tuple_impl<_Idx, _Head, _Tail...>
    : public _Tuple_impl<_Idx + 1, _Tail...>,
      private _Head_base<_Idx, _Head>
{
    typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited;
    constexpr _Tuple_impl() = default;
    constexpr _Tuple_impl(_Tuple_impl&& __in) : _Inherited(std::move(__in)) {}
};

template<typename... _Elements>
struct tuple : public _Tuple_impl<0, _Elements...> {};
Run Code Online (Sandbox Code Playgroud)

当我们实例化时tuple<tuple<tuple<>>>,我们得到了这个继承层次结构:

libstdc ++中<code>_Tuple_impl<1></code>可以通过两种不同的路径访问.这还不是问题,问题出在move构造函数中,它调用了move-conversion构造函数<code>_Tuple_impl<1></code>.<code>_Tuple_impl<1></code>你想要哪个?编译器不知道,因此选择放弃.</p>

<p>(在你的情况下,这是因为<code>_Head_base<0, tuple<>></code>你正在实例化<code>tuple<tuple<>, tuple<tuple<>>></code>,但原则是相同的.)</p>

<hr>

<p>为什么libc ++没有同样的问题?主要有两个原因:</p>

<ol>
<li><code>tuple<T...></code>在libc ++中使用组合而不是继承来引用<code>__tuple_impl<...></code>.</li>
<li>因此,空基类优化<code>__tuple_leaf<tuple<tuple<>>></code>不会启动,即<code>__tuple_leaf<tuple<tuple<>>></code>不会继承<code>tuple<tuple<>></code></li>
<li>因此,不会发生模糊的基类问题.</li>
<li>(并且每个基地都是独特的,如@mitchnull所述,但这不是主要区别.)</li>
</ol>

<p><img rel=