返回一个包含 C 数组的元组

问题描述

我有一些代码可以在 g++ 10.2.0 下编译和运行良好,但被 clang++ 11.0.0 拒绝。

这是该问题的最小重现:

#include <tuple>
#include <cstdint>

struct Dummy { };

using second_t = Dummy;
using example_t = std::tuple<size_t,second_t[8]>;

example_t f() {
    example_t result;
    return result;
}

int main() {
    auto x = f();
    (void) x;
}

在 g++ 中,它编译时没有任何抱怨,但使用 clang++ 我得到:

clang++ --std=c++20 -Wall -Werror main.cpp -o example
In file included from main.cpp:1:
/usr/bin/../lib/gcc/aarch64-unkNown-linux-gnu/10.2.0/../../../../include/c++/10.2.0/tuple:137:4: error: array initializer must be an initializer list
        : _M_head_impl(std::forward<_UHead>(__h)) { }
          ^
/usr/bin/../lib/gcc/aarch64-unkNown-linux-gnu/10.2.0/../../../../include/c++/10.2.0/tuple:375:9: note: in instantiation of function template specialization 'std::_Head_base<1,Dummy [8],false>::_Head_base<Dummy [8]>' requested here
      : _Base(std::forward<_Head>(_M_head(__in))) { }
        ^
/usr/bin/../lib/gcc/aarch64-unkNown-linux-gnu/10.2.0/../../../../include/c++/10.2.0/tuple:236:9: note: in instantiation of member function 'std::_Tuple_impl<1,Dummy [8]>::_Tuple_impl' requested here
      : _Inherited(std::move(_M_tail(__in))),^
/usr/bin/../lib/gcc/aarch64-unkNown-linux-gnu/10.2.0/../../../../include/c++/10.2.0/tuple:996:17: note: in instantiation of member function 'std::_Tuple_impl<0,unsigned long,Dummy [8]>::_Tuple_impl' requested here
      constexpr tuple(tuple&&) = default;
                ^
main.cpp:11:12: note: in defaulted move constructor for 'std::tuple<unsigned long,Dummy [8]>' first required here
    return result;
           ^
1 error generated.
make: *** [Makefile:2: all] Error 1

有趣的是,如果我将 second_t 更改为 int32_t,我也会收到来自 g++ 的错误

g++ --std=c++20 -Wall -Werror main.cpp -o example
In file included from main.cpp:1:
/usr/include/c++/10.2.0/tuple: In instantiation of ‘constexpr std::_Head_base<_Idx,_Head,false>::_Head_base(_UHead&&) [with _UHead = int [8]; long unsigned int _Idx = 1; _Head = int [8]]’:
/usr/include/c++/10.2.0/tuple:375:49:   required from ‘constexpr std::_Tuple_impl<_Idx,_Head>::_Tuple_impl(std::_Tuple_impl<_Idx,_Head>&&) [with long unsigned int _Idx = 1; _Head = int [8]]’
/usr/include/c++/10.2.0/tuple:237:42:   required from ‘constexpr std::_Tuple_impl<_Idx,_Tail ...>::_Tuple_impl(std::_Tuple_impl<_Idx,_Tail ...>&&) [with long unsigned int _Idx = 0; _Head = long unsigned int; _Tail = {int [8]}]’
/usr/include/c++/10.2.0/tuple:996:17:   required from here
/usr/include/c++/10.2.0/tuple:137:42: error: array used as initializer
  137 |  : _M_head_impl(std::forward<_UHead>(__h)) { }
      |                                          ^
make: *** [Makefile:2: all] Error 1

我猜这是因为使用了 C 数组。如果我将代码更改为使用 std::array,问题就会消失。不过,出于好奇,我仍然很好奇是否有办法用 C-array 做到这一点。

所以我的问题是:

  1. g++ 接受这段代码有错吗?
  2. 有没有什么方法可以在这样的元组中返回一个 C 数组,它适用于 g++ 和 clang++?

解决方法

C 数组基本上是指针,请注意,它们不提供也不需要有关数组长度的信息。长度必须单独保存并传递。因此,实现您需要的一种方法是:

  using example_t = std::tuple<size_t,second_t*>;