使用"std::enable_if_t" "function template has already been defined"
"function template has already been defined" using "std::enable_if_t"
我正在尝试使用std::enable_if_t
根据传递给它的类型的特征来切换模板函数的实现。
下面是一个示例:
#include <iostream>
#include <type_traits>
// Enable if "T" is integral
template <typename T,
typename = std::enable_if_t<std::is_integral_v<T>>
>
void print(T value)
{
std::cout << "Integral: " << value << std::endl;
}
// Enable if "T" is not integral
template <typename T,
typename = std::enable_if_t<!std::is_integral_v<T>>
>
void print(T value)
{
std::cout << "Not Integral: " << value << std::endl;
}
int main()
{
int i = 42;
print(i);
double d = 42.0;
print(d);
}
问题是,这无法编译声明:
'void print(T(':函数模板已经定义。
这对我来说感觉很奇怪,因为std::is_integral_v<T>
和!std::is_integral_v<T>
永远不会同时评估为 true,因此每当启用一个实现时,都应该禁用另一个实现。
为什么这不起作用?解决此问题并获得我正在寻找的功能的最佳方法是什么?
CPP 参考:
一个常见的错误是声明两个仅不同的函数模板 在其默认模板参数中。这不起作用,因为 声明被视为同一函数的重新声明 模板(函数中不考虑默认模板参数 模板等效性(。
/*** WRONG ***/ struct T { enum { int_t,float_t } m_type; template <typename Integer, typename = std::enable_if_t<std::is_integral<Integer>::value> > T(Integer) : m_type(int_t) {} template <typename Floating, typename = std::enable_if_t<std::is_floating_point<Floating>::value> > T(Floating) : m_type(float_t) {} // error: treated as redefinition }; /* RIGHT */ struct T { enum { int_t,float_t } m_type; template <typename Integer, std::enable_if_t<std::is_integral<Integer>::value, int> = 0 > T(Integer) : m_type(int_t) {} template <typename Floating, std::enable_if_t<std::is_floating_point<Floating>::value, int> = 0 > T(Floating) : m_type(float_t) {} // OK };
在模板类型中使用enable_if时应小心 命名空间范围函数模板的非类型参数。一些 ABI 像安腾 ABI 这样的规范不包括 非类型模板参数的实例化相关部分 重音,意思是两种不同功能的专业化 模板最终可能会使用相同的损坏名称并出错 链接在一起。例如:
// first translation unit struct X { enum { value1 = true, value2 = true }; }; template<class T, std::enable_if_t<T::value1, int> = 0> void func() {} // #1 template void func<X>(); // #2 // second translation unit struct X { enum { value1 = true, value2 = true }; }; template<class T, std::enable_if_t<T::value2, int> = 0> void func() {} // #3 template void func<X>(); //#4
函数模板 #1 和 #3 具有不同的签名,并且 不同的模板。尽管如此,#2 和 #4,尽管是 不同函数模板的实例化,具有相同的损坏 安腾C++ ABI (_Z4funcI1XLi0EEvv( 中的名称,意思是 链接器会错误地将它们视为同一实体。
修复:
#include <iostream>
#include <type_traits>
// Enable if "T" is integral
template <typename T,
std::enable_if_t<std::is_integral_v<T>, int> = 0
>
void print(T value)
{
std::cout << "Integral: " << value << std::endl;
}
// Enable if "T" is not integral
template <typename T,
std::enable_if_t<!std::is_integral_v<T>, int> = 0
>
void print(T value)
{
std::cout << "Not Integral: " << value << std::endl;
}
int main()
{
int i = 42;
print(i);
double d = 42.0;
print(d);
}
更好的是,使用概念:
#include <iostream>
#include <concepts>
// Enable if "T" is integral
template <std::integral T>
void print(T value)
{
std::cout << "Integral: " << value << std::endl;
}
// Enable if "T" is not integral
template <typename T>
void print(T value)
{
std::cout << "Not Integral: " << value << std::endl;
}
int main()
{
int i = 42;
print(i);
double d = 42.0;
print(d);
}
住
相关文章:
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- 使用"std::enable_if_t" "function template has already been defined"
- 如果两个静态库使用相同的另一个静态库,如何避免"LNK2005 Already Defined error"?
- 使用 gtest 时"_main already defined"
- 使用 GraphicsPath::AddString() 抱怨"class 'GraphicsPath' has no member 'AddString'"
- 'Project.exe has triggered a breakpoint.'
- C++ 结构数组 - "This declaration has no storage class or type specifier"
- Rcpp 'candidate function has different number of parameters (expected 0 but has 1)'
- "... already defined in *.obj"但我没有在同一范围内两次定义任何变量
- 在 EAX 模式下加密数据时"program has stopped working"
- "xvalue has identity"是什么意思?
- 实现多线程后"Project.exe has triggered a breakpoint"
- 为什么删除执行组件指针会导致"Program.exe has triggered a breakpoint"
- "Field has incomplete type"引用自己的类的问题
- 如何在过载时强制"statement has no effect"警告==
- "Function template has already been defined"与相互排斥的"enable_if"一起
- "already has the suffix -ipad. Using it."找不到 Cocos2d-x 图像
- C++ 错误 2084:"already has body"
- 错误 C2084 "already has body"应该编译?
- "class template has already been declared as a non-class template"