c++ enable_if 用于非类型模板参数
c++ enable_if for non-type template parameters
我对部分模板专业化有点困惑...我有一些代码依赖于算术数据类型 T 和小整数 DIM。我希望能够为不同的 DIM 值指定不同的 class 方法。使用部分模板专业化的不可能性促使我探索 enable_if。这正是我所需要的...除了我希望它 return 一个数字而不是一个类型。我怎样才能做到这一点?下面的代码应该可以说明我想要什么。
#include <stdio.h>
#include <iostream>
#include <type_traits>
template <typename T, int DIM>
class foo{
public:
T function();
};
template <typename T, int DIM>
T foo<T, std::enable_if<DIM == 1>::value>::function(){
// do something
return 1.0;
}
template <typename T, int DIM>
T foo<T, std::enable_if<DIM == 2>::value>::function(){
// do something else
return 2342.0;
}
int main(){
foo<int, 1> object;
int ak = object.function();
std::cout << ak << "\n";
return 0;
}
使用 std::integral_constant 类型来包装您的值,如:
std::integral_constant<int, 2>
你完全可以用 enable_if
做你想做的事,只要记住,当条件为假时替换必须失败,所以你必须调用 type
以确保在特化时替换失败各种条件。
#include <stdio.h>
#include <iostream>
#include <type_traits>
template <typename T, int DIM>
class foo
{
public:
template <int D = DIM>
typename std::enable_if<D == 1, T>::type
function()
{
// do something
return 1.0;
}
template <int D = DIM>
typename std::enable_if<D == 2, T>::type
function()
{
// do something else
return 2342.0;
}
};
int main(){
foo<int, 1> object;
int ak = object.function();
std::cout << ak << "\n";
return 0;
}
对于简单的场景,如上面的场景(检查特定值,而不是值的范围),您也可以使用偏特化。但是,如果您想针对 1-50
中的所有值进行专门化,针对 51-200
中的所有值进行专门化,然后针对通用 fallthrough,enable_if
效果很好。
您也可以在模板签名中使用enable_if
。只是一个简单的例子。
#include <stdio.h>
#include <iostream>
#include <type_traits>
template <typename T, int DIM>
class foo
{
public:
template <int D = DIM, typename std::enable_if<D == 1, void>::type* = nullptr>
T function()
{
// do something
return 1.0;
}
template <int D = DIM, typename std::enable_if<D == 2, void>::type* = nullptr>
T function()
{
// do something else
return 2342.0;
}
};
int main(){
foo<int, 1> object;
int ak = object.function();
std::cout << ak << "\n";
return 0;
}
你可以部分特化整个 class:
template <typename T, int DIM>
class foo;
template <typename T>
class foo<T, 1>
{
public:
T function() {
// do something
return 1.0;
}
};
template <typename T>
class foo<T, 2>
{
public:
T function() {
// do something
return 2342.0;
}
};
如果两个专业化之间有很多通用代码,您仍然可以使用继承(从通用部分继承或仅继承专用部分)。
一种简单的替代方法是使用标签调度:
template <typename T, int dim>
class foo
{
public:
T function();
};
template <typename T>
T function_helper(foo<T, 1>&) {
// do something
return 1.0;
}
template <typename T>
T function_helper(foo<T, 2>&) {
// do something
return 2342.0;
}
template <typename T, int dim>
T foo::function() {
return function_helper(*this);
}
但在 C++17 中,if constexpr
允许更简单的语法:
template <typename T, int DIM>
class foo
{
public:
T function() {
if constexpr (DIM == 1) {
// do something
return 1.0;
} else if constexpr (DIM == 2) {
// do something
return 2342.0;
}
}
};
我对部分模板专业化有点困惑...我有一些代码依赖于算术数据类型 T 和小整数 DIM。我希望能够为不同的 DIM 值指定不同的 class 方法。使用部分模板专业化的不可能性促使我探索 enable_if。这正是我所需要的...除了我希望它 return 一个数字而不是一个类型。我怎样才能做到这一点?下面的代码应该可以说明我想要什么。
#include <stdio.h>
#include <iostream>
#include <type_traits>
template <typename T, int DIM>
class foo{
public:
T function();
};
template <typename T, int DIM>
T foo<T, std::enable_if<DIM == 1>::value>::function(){
// do something
return 1.0;
}
template <typename T, int DIM>
T foo<T, std::enable_if<DIM == 2>::value>::function(){
// do something else
return 2342.0;
}
int main(){
foo<int, 1> object;
int ak = object.function();
std::cout << ak << "\n";
return 0;
}
使用 std::integral_constant 类型来包装您的值,如:
std::integral_constant<int, 2>
你完全可以用 enable_if
做你想做的事,只要记住,当条件为假时替换必须失败,所以你必须调用 type
以确保在特化时替换失败各种条件。
#include <stdio.h>
#include <iostream>
#include <type_traits>
template <typename T, int DIM>
class foo
{
public:
template <int D = DIM>
typename std::enable_if<D == 1, T>::type
function()
{
// do something
return 1.0;
}
template <int D = DIM>
typename std::enable_if<D == 2, T>::type
function()
{
// do something else
return 2342.0;
}
};
int main(){
foo<int, 1> object;
int ak = object.function();
std::cout << ak << "\n";
return 0;
}
对于简单的场景,如上面的场景(检查特定值,而不是值的范围),您也可以使用偏特化。但是,如果您想针对 1-50
中的所有值进行专门化,针对 51-200
中的所有值进行专门化,然后针对通用 fallthrough,enable_if
效果很好。
您也可以在模板签名中使用enable_if
。只是一个简单的例子。
#include <stdio.h>
#include <iostream>
#include <type_traits>
template <typename T, int DIM>
class foo
{
public:
template <int D = DIM, typename std::enable_if<D == 1, void>::type* = nullptr>
T function()
{
// do something
return 1.0;
}
template <int D = DIM, typename std::enable_if<D == 2, void>::type* = nullptr>
T function()
{
// do something else
return 2342.0;
}
};
int main(){
foo<int, 1> object;
int ak = object.function();
std::cout << ak << "\n";
return 0;
}
你可以部分特化整个 class:
template <typename T, int DIM>
class foo;
template <typename T>
class foo<T, 1>
{
public:
T function() {
// do something
return 1.0;
}
};
template <typename T>
class foo<T, 2>
{
public:
T function() {
// do something
return 2342.0;
}
};
如果两个专业化之间有很多通用代码,您仍然可以使用继承(从通用部分继承或仅继承专用部分)。
一种简单的替代方法是使用标签调度:
template <typename T, int dim>
class foo
{
public:
T function();
};
template <typename T>
T function_helper(foo<T, 1>&) {
// do something
return 1.0;
}
template <typename T>
T function_helper(foo<T, 2>&) {
// do something
return 2342.0;
}
template <typename T, int dim>
T foo::function() {
return function_helper(*this);
}
但在 C++17 中,if constexpr
允许更简单的语法:
template <typename T, int DIM>
class foo
{
public:
T function() {
if constexpr (DIM == 1) {
// do something
return 1.0;
} else if constexpr (DIM == 2) {
// do something
return 2342.0;
}
}
};