c++ - 简单的 constexpr 函数无法用 GCC 编译(clang 没问题)

标签 c++ language-lawyer c++14 template-meta-programming constexpr

以下代码does not compile使用 GCC 5.2 (C++14)。它does compile使用 clang 3.6 (C++14)。 (原代码可见here)

#include <cstddef>
#include <algorithm>
#include <type_traits>
#include <utility>

template <typename T>
class aggregate_wrapper;

template <typename T, std::size_t n>
class aggregate_wrapper<T[n]> {
public:
  using array = T[n];

  template <typename... Ts, typename = decltype(array{std::declval<Ts>()...})>
  aggregate_wrapper(Ts&&... xs)
      : arr_{std::forward<Ts>(xs)...} {
    // nop
  }

  aggregate_wrapper(const array& arr) {
    std::copy(arr, arr + n, arr_);
  }
  aggregate_wrapper(array&& arr) {
    std::move(arr, arr + n, arr_);
  }

  operator T* () {
    return arr_;
  }
  operator const T* () const {
    return arr_;
  }

  constexpr std::size_t size() const {
    return n;
  }

private:
  array arr_;
};

int main() {
  aggregate_wrapper<int[3]> arr;
  static_assert(arr.size() == 3, "");
}

产生的错误信息是

main.cpp: In function 'int main()':
main.cpp:44:3: error: non-constant condition for static assertion
   static_assert(arr.size() == 3, "");
   ^
main.cpp:44:25: error: call to non-constexpr function 'constexpr std::size_t aggregate_wrapper<T [n]>::size() const [with T = int; long unsigned int n = 3ul; std::size_t = long unsigned int]'
   static_assert(arr.size() == 3, "");
                         ^
main.cpp:34:25: note: 'constexpr std::size_t aggregate_wrapper<T [n]>::size() const [with T = int; long unsigned int n = 3ul; std::size_t = long unsigned int]' is not usable as a constexpr function because:
   constexpr std::size_t size() const {
                         ^
main.cpp:34:25: error: enclosing class of constexpr non-static member function 'constexpr std::size_t aggregate_wrapper<T [n]>::size() const [with T = int; long unsigned int n = 3ul; std::size_t = long unsigned int]' is not a literal type
main.cpp:10:7: note: 'aggregate_wrapper<int [3]>' is not literal because:
 class aggregate_wrapper<T[n]> {
       ^
main.cpp:10:7: note:   'aggregate_wrapper<int [3]>' is not an aggregate, does not have a trivial default constructor, and has no constexpr constructor that is not a copy or move constructor

有什么想法吗?代码是否应该按照标准编译?

最佳答案

或者您可以将现有的可变参数构造函数作为您的 constexpr 构造函数来执行默认构造:

template <typename... Ts, typename = decltype(array{std::declval<Ts>()...})>
constexpr                      // <---- ADD THIS
aggregate_wrapper(Ts&&... xs)
   : arr_{std::forward<Ts>(xs)...} {
   // nop
}

关于c++ - 简单的 constexpr 函数无法用 GCC 编译(clang 没问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35080001/

相关文章:

c++ - 错误 : ‘make_reverse_iterator’ is not a member of ‘std’

c++ - 如何使 Insure++ 与 boost 和 g++ 3.4.x 一起工作

c++ - 为什么我的 printLevel 函数不起作用?

c++ - 使用function-try-block时在Visual Studio中发出C4297警告(假定函数不会引发异常,但会引发异常)

c - 由唯一类型限定符组成的声明说明符

c - C 中的严格别名规则

c++ - 如何使用 MySQL Connector C++ 与数据库建立连接?

c++ - 人口增长模式与预期不符

c++ - 删除类对象的转换函数?

c++ - 理解常量