【发布时间】:2020-03-06 05:56:16
【问题描述】:
我在 x64 Linux 上使用 clang 9.0.1 和 gcc 9.2.1,两者都带有 --std=c++17(或 --std=c++2a)。
Gcc 可以在没有任何错误或警告的情况下构建以下示例,而 clang++ 在 if constexpr 两行都报告了 error: constexpr if condition is not a constant expression。 (顺便说一句,在我的 MacBook 上,Apple clang-11.0.0 也报告了同样的错误。)
MCVE:
#include <utility>
enum class TopicType {
MarketData = 'M',
Timer = 'T',
};
template<class Topic>
struct TopicBase {
constexpr static TopicType type() { return Topic::type; };
const Topic& topicImp;
explicit TopicBase(const Topic &t) : topicImp(t) {}
};
struct MarketDataTopic {
static constexpr TopicType type{TopicType::MarketData};
};
struct TimerTopic {
static constexpr TopicType type{TopicType::Timer};
};
template<class Topic>
int subscribe(TopicBase<Topic>&& topic) {
if constexpr (topic.type() == TopicType::MarketData) { // <-- clang++ reports error here
return 1;
}
if constexpr (topic.type() == TopicType::Timer) { // and error here
return 2;
}
return -1;
}
int main(int argc, const char **argv) {
MarketDataTopic m{};
TimerTopic t{};
TopicBase<MarketDataTopic> b1{m};
TopicBase<TimerTopic> b2{t};
subscribe(std::move(b1));
return 0;
}
在线编译器https://godbolt.org/z/rARi_N 有同样的结果。
那么哪个编译器是正确的呢?如果它是一个错误,如何修复它的clang?
【问题讨论】:
-
Simplified example。左值/右值引用是问题所在。
-
@0x499602D2 似乎与它有关,这是修改后的工作OP代码。 godbolt.org/z/2HiLGe 取值
-
@arnes 是的,按值传递是可以的。但是我需要通过引用传递,结构可能很复杂。
-
@halfelf 我不建议你按值传递,我只是想说明clang的行为可能不是一个错误,可能有我不知道的有意义的解释:(
标签: c++ clang c++17 language-lawyer clang++