"如果constexpr"与"互动并尝试constexpr功能"警告

时间:2017-10-17 00:07:08

标签: c++ c++17 template-meta-programming if-constexpr

我声称this program应该是格式良好的:它声明了S<int>的constexpr成员函数。但是,GCC和Clang都拒绝接受这个计划。

template<class T>
struct S {
    constexpr int foo() {
        if constexpr (std::is_same_v<T, int>) {
            return 0;
        } else {
            try {} catch (...) {}
            return 1;
        }
    }
};

int main()
{
    S<int> s;
    return s.foo();  // expect "return 0"
}
海湾合作委员会说:

  

错误:&#39;尝试&#39; in&#39; constexpr&#39;功能

Clang说:

  

错误:constexpr函数中不允许使用语句

他们似乎都没有注意到&#34;尝试&#34; statement位于if constexpr语句的废弃分支中。

如果我将try / catch分解为非constexpr 成员函数void trycatch(),那么Clang和GCC都会再次对代码感到满意,即使它的行为应该等同于不快乐的版本。

template<class T>
struct S {
    void trycatch() {
        try {} catch (...) {}
    }
    constexpr int foo() {
        if constexpr (std::is_same_v<T, int>) {
            return 0;
        } else {
            trycatch();  // This is fine.
            return 1;
        }
    }
};

这是

  • GCC和Clang的错误?
  • 标准中的缺陷,GCC和Clang是否忠实执行?
  • 由于foo()的{​​{3}}而导致的实施质量问题?

(不相关的背景:我正在为分配器感知版本any::emplace<T>()实施constexpr any,其分配器可能是constexpr-per - "conditional constexprness"(即它可能缺少deallocate会员功能)或者可能没有。在前一种情况下,我们不想要或不需要try;在后一种情况下,我们需要try才能调用{deallocate 1}}如果T的构造函数抛出。)

1 个答案:

答案 0 :(得分:11)

编制者遵守标准。 C ++ 17草案N4659说([dcl.constexpr] /(3.4.4)):

  

constexpr函数的定义应满足以下要求:

     
      
  • ...

  •   
  • function-body 应为= delete= default复合语句,不包含

         
        
    • ...

    •   
    • try-block

    •   
    • ...

    •   
  •   

elseS<int>::foo语句中的“废弃语句”的规则都没有覆盖此规则。关于废弃语句的唯一特殊事项是废弃语句没有实例化,废弃语句中的odr-uses不会导致需要使用声明的定义,并且在确定真实返回时忽略丢弃的return语句具有占位符返回类型的函数的类型。

我没有看到任何现有的C ++问题讨论这个问题,提出if constexpr的论文P0292R1没有解决与constexpr函数的交互问题。