2016-08-12 26 views
0

(請參閱末尾的澄清說明)不必用bools和模板參數列出所有可能性

我試圖使用bool's作爲模板參數。我希望能夠寫這樣的事情

#include <iostream> 
#include <string> 

template<bool a, bool b> 
void foo() { 
    printf("%d %d\n", (int)a, (int)b); 
} 

int main() 
{ 
    int c = 2 ; 
    c += 2 % 4 - 3 + 1 ; 
    bool a = c % 2 == 0 ; 
    bool b = c % 2 == 1 ; 
    foo<a, b>(); 
} 

但是,正如所料,我有一個

16:9: error: the value of 'a' is not usable in a constant expression 14:10: note: 'bool a' is not const

我當然可以做類似

#include <iostream> 
#include <string> 

template<bool a, bool b> 
void foo() { 
    printf("%d %d\n", (int)a, (int)b); 
} 

int main() 
{ 
    int c = 2 ; 
    c += 2 % 4 - 3 + 1 ; 
    bool a = c % 2 == 0 ; 
    bool b = c % 2 == 1 ; 
    if(a) { 
     if(b) { 
      foo<true,true>(); 
     } else { 
      foo<true,false>(); 
     } 
    } else { 
     if(b) { 
      foo<false,true>(); 
     } else { 
      foo<false,false>(); 
     } 
    } 
} 

但它的有點討厭。由於a和b都是bools,有沒有辦法不必明確列出所有可能性?編譯器能夠自行解決這個問題嗎?

編輯:澄清:我瞭解模板是編譯時間「變量」。我的問題是,編譯器能夠自動生成所有函數,基於bool是真/假的事實(所以它是值的一個「範圍」,這是在某種意義上使用模板所需的),以及然後添加所需的「管道」,以便在運行時選擇正確的功能。

謝謝,

+0

模板是在編譯時決定,但你要選擇在運行時執行。因此,模板可能不是你想要的。 – pingul

+0

我同意。我的確是這樣的,因爲它是一個布爾(無論是真的還是假的,沒有別的),也許編譯器可以根據可能性自動生成所需的函數。 – leo

+0

我明白,從編譯器中可能有點太多了,但是:-) – leo

回答

4

模板參數在編譯時進行評估。現在考慮您的示例的這一修改:

#include <iostream> 
#include <string> 

template<bool a, bool b> 
void foo() { 
    printf("%d %d\n", (int)a, (int)b); 
} 

int main() 
{ 
    int c = 2 ; 

    std::cin >> c;   

    bool a = c % 2 == 0 ; 
    bool b = c % 2 == 1 ; 
    foo<a, b>(); 
} 

在這裏,有沒有辦法如何在編譯時評估。不幸的是編譯器無法區分這兩個例子。

編譯器不能生成所有的功能本身(如果你有整型,你會希望它產生2層** 32-1的功能呢?),除非你問到我的:

#include <iostream> 
#include <map> 
#include <functional> 

template <bool a, bool b> 
void func() { 
    std::cout << std::boolalpha << a << " " << std::boolalpha << b << std::endl; 
} 

std::map<bool, std::map<bool, std::function<void()>>> dispatcher; 

template <bool a, bool b> 
void register_dispatcher() { 
    dispatcher[a][b] = func<a,b>; 
} 

int main() { 
    register_dispatcher<false, false>(); 
    register_dispatcher<false, true>(); 
    register_dispatcher<true, false>(); 
    register_dispatcher<true, true>(); 

    bool a, b; 
    a = false; 
    b = true; 

    dispatcher[a][b](); 
    // for clarity I don't handle nonexistent keys 

    return 0; 
} 

注意,代碼需要C++ 11。

現在你可能需要10個bool參數並生成它們中的每一個。當心,這是1024個功能。沒有那麼多,但要小心。讓我們用3來做:

#include <iostream> 
#include <map> 
#include <functional> 

template <bool a, bool b, bool c> 
void func() { 
    std::cout 
     << std::boolalpha << a << " " 
     << std::boolalpha << b << " " 
     << std::boolalpha << c << " " 
     << std::endl; 
} 

std::map<bool, std::map<bool, std::map<bool, std::function<void()>>>> dispatcher; 

template <bool a, bool b, bool c> 
void register_dispatcher() { 
    dispatcher[a][b][c] = func<a,b, c>; 
} 

template <bool a, bool b> 
void register_dispatcher_2() { 
    register_dispatcher<a, b, true>(); 
    register_dispatcher<a, b, false>(); 
} 

template <bool a> 
void register_dispatcher_1() { 
    register_dispatcher_2<a, true>(); 
    register_dispatcher_2<a, false>(); 
} 

void register_dispatcher_0() { 
    register_dispatcher_1<true>(); 
    register_dispatcher_1<false>(); 
} 

int main() { 
    register_dispatcher_0(); 

    bool a, b, c; 
    a = false; 
    b = true; 
    c = true; 

    dispatcher[a][b][c](); 

    return 0; 
} 

該代碼一次生成一個參數。在7或8個參數中,或者當您開始以ints進行混合時,它會開始值得。

+0

我明白了,但正如思考編譯器生成所有可能的值(它是一個bool,因此它是有限的),然後在運行時選擇正確的函數(請參閱編輯問題)。 – leo

+0

@leo:answer extended –

+0

很酷,謝謝你的回答。 – leo

1

通過添加一些const/constexpr,你可以做

constexpr int c_ini = 2 ; 
constexpr int c = c_ini + 2 % 4 - 3 + 1 ; 
constexpr bool a = c % 2 == 0 ; 
constexpr bool b = c % 2 == 1 ; 
foo<a, b>(); 

Demo

相關問題