【问题标题】:Clang report "constexpr if condition is not a constant expression" while GCC is ok [duplicate]当 GCC 正常时,Clang 报告“constexpr if condition is not a constant expression”[重复]
【发布时间】: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++


【解决方案1】:

您可以这样做以使其适用于 clang:

template<class Topic>
int subscribe(TopicBase<Topic>&& topic) {
    using myType = TopicBase<Topic>;
    if constexpr (myType::type() == TopicType::MarketData) { // <-- clang++ reports error here
        return 1;
    }
    if constexpr (myType::type() == TopicType::Timer) { // and error here
        return 2;
    }

    return -1;
}

Run live

这很可能是 clang 中的一个错误。最好举报。

【讨论】:

  • 其实,好像和右值引用有关,当我们通过TopicBase&lt;Topic&gt; topic取对象值时,它起作用了,但我不知道为什么。
  • 谢谢,点赞。我之前对 if constexpr 条件不是很熟悉,标准中有关于这种奇怪行为的一些解释吗?
  • @halfelf 也许您需要一个“语言律师”标签。
  • @arnes 所以事实证明 clang 是正确的 (stackoverflow.com/questions/44995196/…)。祝福 cpp 众神。
猜你喜欢
  • 2016-06-19
  • 1970-01-01
  • 2022-08-08
  • 1970-01-01
  • 2018-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多