模仿"如果constexpr"行为,不可能?

时间:2016-08-24 14:11:05

标签: c++ templates if-statement constexpr c++17

我的编译器不支持if constexpr,但我被它的好处所吸引。
我必须拥有它 - 即使它可能是假的。

此代码是我模仿if constexpr行为的尝试 目标是使行(###)只出现在1个函数中: -

#include <iostream>
using namespace std;

template<bool Flag,typename F> constexpr typename std::enable_if<!Flag, void>::type iter_(F f,int i1){
    f(i1); //No!  The compiler still tried to compile even Flag=true
}
template<bool Flag,typename F> constexpr typename std::enable_if<Flag, void>::type iter_(F f,int i1){   }
template<bool Flag,typename F> constexpr typename std::enable_if<Flag, void>::type iter_(F f,int i1,int i2){
    f(i1,i2); //No!  The compiler still tried to compile even Flag=false
}
template<bool Flag,typename F> constexpr typename std::enable_if<!Flag, void>::type iter_(F f,int i1,int i2){}

template<bool Flag,typename F> constexpr void fff(  F f  ){
    for(int n=0;n<5;n++){//fake loop, the real situation is very complex
        //### some horror code appeared here, but omitted
        if(Flag){//attempt to mimic "if constexpr"
            iter_<true>(f,1,2);
        }else{
            iter_<false>(f,3);
        }
    }
}

这是它的用法: -

template<typename F> constexpr void fff1(  F f  ){fff<false>(f);} //usage
template<typename F> constexpr void fff2(  F f  ){fff<true>(f);} //usage

int main() {
    // your code goes here
    auto f1=[&](int a){
        cout<<a<<" ";   
    };
    auto f2=[&](int a,int b){
        cout<<a<<" "<<b<<endl;  
    };
    fff1(f1);
    fff2(f2);
    return 0;
}

我收到了编译错误:

prog.cpp: In instantiation of 'constexpr typename std::enable_if<Flag, void>::type iter_(F, int, int) [with bool Flag = true; F = main()::<lambda(int)>; typename std::enable_if<Flag, void>::type = void]':
prog.cpp:16:18:   required from 'constexpr void fff(F) [with bool Flag = false; F = main()::<lambda(int)>]'
prog.cpp:22:61:   required from 'constexpr void fff1(F) [with F = main()::<lambda(int)>]'
prog.cpp:33:9:   required from here
prog.cpp:9:3: error: no match for call to '(main()::<lambda(int)>) (int&, int&)'
  f(i1,i2);
   ^
prog.cpp:9:3: note: candidate: void (*)(int) <conversion>
prog.cpp:9:3: note:   candidate expects 2 arguments, 3 provided

从错误中可以清楚地看到,即使函数有 std :: enable_if [有效 FALSE] ,  编译器仍然编译函数内部的代码。  - 那很不好。

我需要编辑哪些部分?
......还是有其他选择吗? ......或者根本不可能模仿if constexpr(这就是它最终被引入的原因)?

1 个答案:

答案 0 :(得分:3)

阅读本文:http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0128r1.html

  

我们不能用现有的语言功能吗?

     

John Spicer在c ++ std-ext-17099中建议使用多态lambda   结合决策模板将提供足够的   设施无需添加新的语言功能。调用   该决策模板看起来大致如下:

template <int arg, typename ... Args> int do_something(Args... args) {
    return static_if<sizeof...(args)>::get(
        [](auto x, auto y) { return x+y; },
        [](auto x) { return *x; })(args...);
}
     

现在,与提议的语言工具相比,我们做了

template <int arg, typename ... Args> int do_something(Args... args) {
    constexpr if (sizeof...(args)) {
        return (args + ...);
    } constexpr_else {
        return *args...;
    }
}

现在这是另一种选择。如果不同的分支返回不同的类型,它会变得更复杂。

此外,

  

我必须在这里指出一些事情:

     
      
  • 我可以在constexpr中返回,中断,继续并转到if   块。我不能在lambda中做到这一点。

  •   
  • 虽然我很聪明   我发现,使用lambdas建立新的控制设施的支持者   constexpr如果解决方案无限可读。

  •   

此外,

  理查德史密斯解释说:

     
    

是的,当实例化一个函数模板时,所有的     其中的声明/语句/表达式被实例化,并且     其中包括本地类,通用lambdas等中的部分。

         

这种通用lambda体的实例化实际上是必要的     我们的语言语义 - 计算通用lambda的捕获     在功能模板中,专业化依赖于我们已经     实例化完整闭包类型及其调用操作符模板     到了我们知道odr-uses在哪里的地步     身体内的非依赖性完整表达。

  
     

相比之下,constexpr的意图是没有采取分支   没有实例化。