2016-08-24 21 views
3

我的編譯器不支持if constexpr,但我被它的好處所吸引。
我必須擁有它 - 即使它可能是假的。模仿「如果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

是的,模板中的所有代碼都必須是有效的。所以不,沒有辦法讓'if'具有對模板無效的分支,並且仍然能夠爲該模板實例化。 – bolov

+1

你在說什麼,如果constexpr?在C++ 11中沒有這樣的東西...... – rubenvb

+1

@rubenvb如果constexpr將在C++中17 – Eugene

回答

3

閱讀:http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0128r1.html

我們不能做到這一點與現有的語言功能?

約翰·斯派塞在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內。我不能在lambda內做到這一點。

  • 雖然我使用lambda表達式來創建新的控制設備的一大 支持者,我發現 的constexpr如果解決方案更具可讀性。

此外,

理查德·史密斯解釋如下:

右鍵,當一個函數模板實例,所有的 聲明/說明/內它表達的是實例化和 ,其中包括本地類,通用lambdas等內的片段。

通用拉姆達機構的這種實例是必要的 我們的語言語義的事實 - 計算函數模板特殊化內的通用拉姆達 的捕獲依賴於在已經我們 實例化的完全封閉的類型和調用操作模板 到我們知道odr用法在正文內的非依賴完整表達式內的位置。

相比之下,constexpr if的意圖是沒有采取 未被實例化的分支。

+0

請注意,Boost.Hana具有這樣的功能:['hana :: if_'](https://boostorg.github.io/hana/#tutorial-integral-branching)。就實例化而言,如果它們是通用lambdas,它不會實例化未分支的分支。基於理查德的評論,這可能還有更多的代碼。 – chris