C++ “if constexpr”能否用于声明具有不同类型和init expr的变量

C++ “if constexpr”能否用于声明具有不同类型和init expr的变量,c++,metaprogramming,c++17,if-constexpr,C++,Metaprogramming,C++17,If Constexpr,例如: void foo() { if constexpr (...) int x = 5; else double x = 10.0; bar(x); // calls different overloads of bar with different values } 这在D语言中很常见,但我没有找到关于C++17的信息 当然,也可以使用类似 std::conditional<..., int, double>::type

例如:

void foo()
{
    if constexpr (...)
        int x = 5;
    else
        double x = 10.0;
    bar(x); // calls different overloads of bar with different values
}
这在D语言中很常见,但我没有找到关于C++17的信息

当然,也可以使用类似

std::conditional<..., int, double>::type x;
std::conditional::type x;

但仅在基本情况下。即使是不同的初始化器(如上所述)也会产生很大的问题。

有两种方法不起作用

首先,变量被限制在其声明的范围内。省略大括号并不会愚弄编译器:
intx=5
仍然在它自己的范围内,并且在它出现后立即消失


其次,
if-constexpr
的宽松语法规则只适用于
if-constexpr
的主体。允许正文中创建的上下文泄漏到周围的范围是不可行的,因为根据定义,它可能格式不好,或者在then/else块之间不一致。(如果else块声明
x
为typename怎么办?)


总之,您需要将
bar()
移动到if主体中,或者将模板
foo()
本身移动,并由您的
确定
x
的类型和值。…

此代码无法工作。问题是调用
bar
时,
x
超出范围。但有一个解决办法:

constexpr auto t = []() -> auto {
  if constexpr(/* condition */) return 1;
  else return 2.9;
}();

bar(t);
稍微解释一下,它使用即时调用的lambda表达式以及自动返回类型推断。因此,我们在适当的地方给出t值,它不会超出范围


当然,如果if语句不能在编译时进行计算,那么它就不起作用了。如果您想在这个lambda中执行一些运行时操作,您不能让t作为constexpr,但它仍然可以工作。

不,由于范围限制,这是不可能的。而是调用
if
else
中的函数。可能还有其他的解决方案,但如果不知道这应该解决什么问题,也不知道它的用例,此时就不可能说得更多了。在调用
bar()
时,两个变量都不存在。您的问题只是不适定的,与
constexpr
“调用内部函数”无关,这意味着所有代码的重复,并可能与多个if表达式相结合。如果分支没有作用域,则为D静态。如果你真的想要一个作用域,你仍然可以添加额外的{}。@aaalex88:重载解析不能动态发生;为
bar(x)
选择的函数在编译时必须是已知的。@而且它不是:
if
是constexpr,所以
x
的类型在编译时是已知的“如果else块声明x为typename怎么办?”-当然,程序格式不正确。上面已经说过:如果我们有几个静态条件,它们需要具有相同代码的指数数量的分支,所以移动
不是最好的解决方案。同样在D
static if
中,如果不创建作用域,那么这是语言设计的失败。不要将
constepr if
误认为
static if
。两者的目的完全不同:一个有条件地启用一个块,另一个有条件地启用注入到周围块中的多行代码。如果你想提出“代码>静态”,如果作为C++的一个特性,可以找到工作组。不用麻烦。如果首先提出的是D型
静态。它在火焰中熄灭了。@aad的static if没有故意创建作用域。Static if/else是一个代码生成构造,就像Static foreach一样。为他们感到抱歉,这篇文章写得有点粗心大意,只是为了得到一个想法。是的,在很多情况下它都会很有帮助。是否可以根据运行时函数参数使
auto t=[&]()->auto{…/*某些代码,但仍然使用constexpr if语句*/…}
?@aaalex否。我已经测试过了。它完全不能依赖于运行时参数。若它这样做了,编译器将抱怨它不能计算constexpr,或者若您删除了constexpr,它将不能计算auto。因此,在这种情况下没有运行时条件。如果您使用t const而不是constexpr,它可以在运行时计算值,但返回类型必须在编译时清除。@aaalex88您完全可以执行类似于
[](int x)->auto{If constexpr(/*condition*/)返回sqrt(x);否则返回x;}(someRuntimeInt)
;基本上,
/*条件*/
中的部分需要是
constepr
,而分支中的实际代码可以是运行时代码