2013-10-14 63 views
1

這裏是我當前的代碼:C++元編程急於評價

template<int n> 
struct N{ 
    static const int k = (n >= 2) ? (1 + N<n-2>::k) : N<0>::k; 
}; 

template<> 
struct N<0>{ 
    static const int k = 0; 
}; 

下編譯:

int main(int, char *[]) 
{ 
    cout << N<2>::k; 
    getchar(); 
} 

下無法編譯:

int main(int, char *[]) 
{ 
    cout << N<1>::k; 
    getchar(); 
} 

是編譯器的熱切計算?:操作符的右分支?如果是這樣,我怎麼才能讓它懶洋洋地評價?

+0

什麼是編譯錯誤? – pippin1289

+0

錯誤是:錯誤C1202:遞歸類型或函數依賴關係上下文過於複雜。 我期待if語句只評估所需的分支。 –

+0

簡單:添加基本案例N <1>,因爲奇數不會碰到N <0>。 – knivil

回答

1

爲了使這個例子工作:

template<int n> 
struct N{ 
    static const int k = 1 + N<n-2>::k; 
}; 

template<> 
struct N<1>{ 
    static const int k = 0; 
}; 

template<> 
struct N<0>{ 
    static const int k = 0; 
}; 

問題在於N<n-2>。當n=1這將導致無限的模板實例化深度。所以這隻能部分回答這個問題,但我不認爲你可以強制模板被懶惰地評估。

+0

關於懶惰評價:可以提升幫忙嗎? –

+0

不確定是否誠實。我不知道任何提升懶惰評估原語。 – pippin1289

+0

懶惰評估是可能的(或者它可能是我的誤解),但代碼對於函數的價值來說是無法忍受的。)我的實現在這裏:https://gist.github.com/kinchungwong/7700777 – rwong

5

如果你要與模板特做到這一點,這就是我會用整個:

template<int n> 
struct N{ 
    static const int k = 1 + N<n-2>::k; 
}; 

template<> 
struct N<1>{ 
    static const int k = 0; 
}; 

template<> 
struct N<0>{ 
    static const int k = 0; 
}; 

除非你在使用模板做這一套,我一般喜歡這樣的:

int constexpr N(int n) { return n/2; } 
+0

: )+1即使留作模板,也可以使用相同的公式進行簡化! –

+0

@DavidRodríguez-dribeas:好點(特別是如果你的編譯器不支持'constexpr')。 –

1

這似乎是工作,可以很容易地推廣到需要用一個懶惰的評估結構來代替三元運算符?案件:

#include <iostream> 

template<int n, bool = (n >= 2)> 
struct N; 

template<> 
struct N<0, false>{ 
    static const int k = 0; 
}; 

template<int n> 
struct N<n, true> { 
    static const int k = 1 + N<n-2>::k; 
}; 

template<int n> 
struct N<n, false> { 
    static const int k = N<0>::k; 
}; 

int main() { 
    std::cout << N<2>::k << '\n'; 
    std::cout << N<1>::k << '\n'; 
} 

但是,使用C++ 11 constexpr函數,此實現已過時。