2016-03-07 120 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

或者你可以用空结构替换枚举。

或者说,什么是更好的,你可以尝试实现它没有模板,并为维创建类,并且每个每个维度一个对象。