2016-03-07 166 views
0

我目前正在寫一個程序NURBS surfaces,在那裏你可以在兩個方向(UV)執行算法的工作。爲了避免代碼重複,我嘗試使用模板,但我沒有經驗使用它們。這裏是我想要做什麼的一個小例子:C++模板專門干將

#include <iostream> 

enum class Dir { 
    U, V 
}; 

struct Foo { 

    unsigned cu, cv; 

    Foo(unsigned cu, unsigned cv) : cu(cu), cv(cv) {}; 

    template<Dir> 
    const Dir otherDir(); 

    template<> 
    const Dir otherDir<Dir::V>() { 
     return Dir::U; 
    } 

    template<> 
    const Dir otherDir<Dir::U>() { 
     return Dir::V; 
    } 

    template<Dir> 
    unsigned count(); 

    template<> 
    unsigned count<Dir::U>() { 
     return cu; 
    } 

    template<> 
    unsigned count<Dir::V>() { 
     return cv; 
    } 

    template<Dir d> 
    unsigned totalCount() { 
     auto c = count<d>(); 
     auto cOther = count<otherDir<d>()>(); 
     return c * cOther; 
    } 

}; 

int main() { 
    Foo f(3,2); 
    std::cout << (f.count<Dir::U>() == 3) << std::endl; 
    std::cout << (f.otherDir<Dir::U>() == Dir::V) << std::endl; 
    std::cout << f.totalCount<Dir::U>() << std::endl; 
} 

但這並不編譯由於主要的最後一行(VS2015,但我不認爲這是編譯器的故障):

1>...\main.cpp(42): error C2672: 'Foo::count': no matching overloaded function found 
1>...\main.cpp(52): note: see reference to function template instantiation 'unsigned int Foo::totalCount<Dir::U>(void)' being compiled 
1>...\main.cpp(42): error C2975: 'unnamed-parameter': invalid template argument for 'Foo::count', expected compile-time constant expression 
1>...\main.cpp(27): note: see declaration of 'unnamed-parameter' 
1>...\main.cpp(43): error C3536: 'cOther': cannot be used before it is initialized 

只有這樣我得到了接近上述功能是通過指定兩個主方向以及其他方向這樣的模板參數:

struct Foo { 

    ... 

    template<Dir d, Dir otherD> 
    unsigned totalCount() { 
     auto c = count<d>(); 
     auto cOther = count<otherD>(); 
     return c * cOther; 
    } 

}; 

int main() { 
    Foo f(3,2); 
    std::cout << f.totalCount<Dir::U, Dir::V>() << std::endl; 
} 

,但似乎並不很優雅。

+0

旁註:要小心VS非標準擴展,上述不與G ++編譯,即使沒有'totalCount'(見http://stackoverflow.com/questions/2097811/c-syntax-for-explicit-specialization-of-a-template-function-in-a-template-clas )。 – Holt

+0

我真的沒有在這裏看到有模板的觀點,爲什麼不簡單地將方向作爲參數傳遞給函數呢? – Holt

+0

'otherDir ()'不是'constexpr',不能在模板參數中使用。 – Jarod42

回答

0

otherDir<d>()不是constexpr,並且不能在模板參數(count<otherDir<d>()>())中使用。

您可以添加constexpr(和static),以該方法, 或使用舊的結構來處理:

template <Dir> struct otherDir; 

template<> 
struct otherDir<Dir::U> 
{ 
    static constexpr Dir value = Dir::V; 
}; 

template<> 
struct otherDir<Dir::V> 
{ 
    static constexpr Dir value = Dir::U; 
}; 

Demo

+0

謝謝,使'otherDir''constexpr static'有所幫助。 – Nakamp

0

也許,問題就在這裏:

auto cOther = count<otherDir<d>()>(); 

模板在編譯時 「已解決」。您應該使用constexpr作爲otherDir<d>(),因爲只是簡單的const並不意味着可以在編譯時評估該方法。

更傳統的做法是有結構otherDir而不是方法。創建結構模板,兩個實例將與static const value = VU

或者你可以用空結構替換枚舉。

或者說,什麼是更好的,你可以嘗試實現它沒有模板,併爲維創建類,並且每個每個維度一個對象。