连续调用constexpr函数时出现编译器错误

时间:2019-09-13 11:34:40

标签: gcc compiler-errors clang c++17 constexpr

我有以下示例:

#include <cstdint>


template<typename T>
struct a_size {
    constexpr static std::size_t size() { return sizeof(T); }
};

template<typename T>
constexpr std::size_t foo(T const& t) {
    constexpr auto result = a_size<decltype(t)>::size();
    return result;
}
template<typename T>
constexpr std::size_t bar(T const& t) {
    constexpr auto result = foo(t);
    return result;
}

int main() {
    constexpr auto r = bar('c');
    return r;
}

使用g++ (Ubuntu 7.3.0-27ubuntu1~18.04) 7.3.0进行编译时,一切似乎都很好。但是,当我使用clang++(版本:clang version 10.0.0 (https://github.com/llvm-mirror/clang.git df2d9221d77042d6b07a6025edf9e810f1801ef5) (https://github.com/llvm-mirror/llvm.git a1e2fd38b595bd636661ac7416961e029c7e1689))进行编译时,出现以下错误:

main.cc:16:33: error: constexpr variable 'result' must be initialized by a constant expression
    constexpr auto result = foo(t);
                        ~~~~^~
main.cc:21:24: note: in instantiation of function template specialization 'bar<char>' requested here
    constexpr auto r = bar('c');
                       ^
1 error generated.

我在godbolt.orgclang 8.0.0的{​​{1}}上观察到类似的行为,该示例有效,但是,clang trunk和{{1 }}。

编译为

  1. GCC
  2. 9.2.0

问题

  1. 为什么会这样?
  2. 为什么在整个通话链中都{/ {1}}-essness transitive 不能被应用/使用(由于缺少更好的单词)? (据我了解,由于某些原因,调用trunk的结果未标记为clang++ -std=c++17 main.cc -o main.run。问题在于原因。)
  3. 哪个编译器正确
  4. 标准怎么说?
  5. 这是一个错误吗?如果是这样,是在g++ -std=c++17 main.cc -o main.run还是constexpr中?
  6. 为什么要删除foo(t)中的引用(constexpr)才能解决问题,而GCC/G++不再产生编译错误?

编辑(16.09.2019)

显然,删除中间变量Clang可解决此问题(如David Ledger所建议)。但这不能回答其他问题。更不用说某些用例可能需要这样的中间变量。

0 个答案:

没有答案