gpt4 book ai didi

c++ - 空嵌套元组错误

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:14:43 24 4
gpt4 key购买 nike

#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 中测试)

是否有可能的解决方法?

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.

最佳答案

看起来您在 libstdc++ 中发现了一个错误! (这段代码在 clang 中与 libc++ 一起工作)。简化的测试用例:

#include <tuple>

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

问题是由于如何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...> {};

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

inheritance diagram of <code>tuple<tuple<tuple<>>></code> in libstdc++

我们看到 _Tuple_impl<1>可以通过两条不同的路径到达。这还不是问题,问题出在move构造函数,它调用了_Tuple_impl<1>的move-conversion构造函数.哪个_Tuple_impl<1>你想要?编译器不知道,所以选择放弃。

(在您的情况下,这是因为 _Head_base<0, tuple<>>,因为您正在实例化 tuple<tuple<>, tuple<tuple<>>>,但原理是相同的。)


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

  1. tuple<T...>在 libc++ 中使用组合而不是继承来引用 __tuple_impl<...> .
  2. 因此,__tuple_leaf<tuple<tuple<>>> 中的空基类优化不会启动,即 __tuple_leaf<tuple<tuple<>>>不会继承 tuple<tuple<>>
  3. 因此不会出现基类不明确的问题。
  4. (正如@mitchnull 所提到的,每个碱基都是独一无二的,但这不是这里的主要区别。)

inheritance diagram of <code>tuple<tuple<tuple<>>></code> in libc++

正如我们在上面看到的,如果 tuple<...>使用继承而不是组合,OP 的 tuple<tuple<>, tuple<tuple<>>>仍将继承自 __tuple_leaf<0, tuple<>>两次,这可能是个问题。

关于c++ - 空嵌套元组错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10999062/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com