c – 空嵌套元组错误

前端之家收集整理的这篇文章主要介绍了c – 空嵌套元组错误前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
#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
}

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

有可能的解决方法吗?

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,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,std::is_empty<class tuple<> >::value>
    struct std::_Tuple_impl<0,class std::tuple<class std::tuple<> > > -> _Head_base<0UL,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<> > >::_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<> > >::_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.

解决方法

看起来你在libstdc中发现了一个错误! (此代码与libc合作).减少测试用例:
#include <tuple>

int main(){
    auto b = std::tuple<std::tuple<std::tuple<>>>{};
}

问题是由于如何在libstdc中实现std :: tuple.元组实现使用具有多重继承的“递归”.你可以想到元组< X,Y,Z>从X和元组继承< Y,Z>.这意味着元组< 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...> {};

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

我们看到_Tuple_impl< 1>可以在两个不同的路径中到达.这还不是问题,问题在于移动构造函数,它调用_Tuple_impl< 1>的移动转换构造函数.哪个_Tuple_impl< 1>你想要?编译器不知道,因此选择放弃.

(在你的情况下,这是因为_Head_base< 0,tuple<>>因为你正在实例化元组< tuple<>,tuple< tuple<>>>而是原则是相同的.)

为什么libc没有同样的问题?主要有两个原因:

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

如上所述,如果元组< ...>使用继承而不是组合,OP的元组< tuple<>,tuple< tuple<>>>仍将继承自__tuple_leaf< 0,tuple<>>两次,这可能是个问题.

猜你在找的C&C++相关文章