C++ 模板专用吸气剂
C++ template specialized getters
我目前正在编写一个使用 NURBS surfaces
的程序,您可以在其中执行两个方向的算法(U
和 V
)。为了避免代码重复,我尝试使用模板,但我从来没有使用它们的经验。这是我想做的一个小例子:
#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;
}
但是由于 main 中的最后一行(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;
}
但是这样好像不是很优雅
大概问题出在这里:
auto cOther = count<otherDir<d>()>();
模板在编译时 "resolved"。您应该将 constexpr
用于 otherDir<d>()
,因为简单的 const
并不意味着可以在编译时评估该方法。
更传统的方法是使用结构 otherDir
而不是方法。创建结构模板,两个实例化将使用 static const value = V
或 U
.
或者您可以用空结构替换枚举。
或者,更好的是,您可以尝试在没有模板的情况下实现它,并为维度创建 class 并为每个维度创建一个对象。
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;
};
我目前正在编写一个使用 NURBS surfaces
的程序,您可以在其中执行两个方向的算法(U
和 V
)。为了避免代码重复,我尝试使用模板,但我从来没有使用它们的经验。这是我想做的一个小例子:
#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;
}
但是由于 main 中的最后一行(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;
}
但是这样好像不是很优雅
大概问题出在这里:
auto cOther = count<otherDir<d>()>();
模板在编译时 "resolved"。您应该将 constexpr
用于 otherDir<d>()
,因为简单的 const
并不意味着可以在编译时评估该方法。
更传统的方法是使用结构 otherDir
而不是方法。创建结构模板,两个实例化将使用 static const value = V
或 U
.
或者您可以用空结构替换枚举。
或者,更好的是,您可以尝试在没有模板的情况下实现它,并为维度创建 class 并为每个维度创建一个对象。
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;
};