如果 constexpr not-taken 分支不需要有效,确定吗?

if constexpr not-taken branch doesn't need to be valid, sure?

我正在测试下面的代码:

#define TO_STRING(X) #X

#define TEST(X, Y) namespace Y { constexpr std::string_view name{#X}, raw_value{TO_STRING(X)};\
constexpr bool defined {name!=raw_value}; constexpr bool has_value{raw_value!=""}; }

#define A
#define B 1

TEST(A, a);
TEST(B, b);
TEST(C, c);

int main()
{
    if constexpr (a::defined && a::has_value) {
        std::cout << a::name << " = " << a::raw_value << '\n';
    } else {
        std::cout << a::name << " not defined or have no value\n";
    }
    if constexpr (b::defined && b::has_value) {
        std::cout << b::name << " = " << b::raw_value << '\n';
    } else {
        std::cout << b::name << " not defined or have no value\n";
    }
    if constexpr (c::defined && c::has_value) {
        std::cout << c::name << " = " << c::raw_value << '\n';
    } else {
        std::cout << c::name << " not defined or have no value\n";
    }
    return 0;
}

产生以下输出:

A not defined or have no value
B = 1
C not defined or have no value

如果我修改TEST添加一个新函数:

#define TEST(X, Y) namespace Y { constexpr std::string_view name{#X}, raw_value{TO_STRING(X)};\
constexpr bool defined {name!=raw_value}; constexpr bool has_value{raw_value!=""};\
constexpr auto value() { if constexpr (defined && has_value) return X; else return; } }

我原以为编译器在扩展 TEST(C, c) 宏时会忽略 return X 语句,它却报告错误:

error: use of undeclared identifier 'C'
TEST(C, c);
     ^

引用未声明的标识符绝对是错误的,但我希望编译器忽略它,因为我认为 if constexpr 未采用的分支不需要格式正确。有没有办法实现这种行为?

[stmt.if]/2

If the value of the ... condition is false, the first substatement [aka the first branch] is a discarded statement, otherwise the second substatement, if present, is a discarded statement. During the instantiation of an enclosing templated entity ..., if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.

(大胆的矿)

这解释了模板内部 if constexpr 的行为。由于没有其他关于它的说法,它在模板之外的行为与普通 if.

的行为相匹配

现在,如果您正在考虑通过添加一个未使用的模板参数使您的函数成为一个模板,它不会那么容易工作:

[temp.res.general]/6.1

The program is ill-formed, no diagnostic required, if:

— no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated

(大胆的矿)