C++ 模板函数实现不正确
C++ template function implementation is not correct
我在这里实现了这个功能(在单个头文件中)。
//header.h
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <stdint.h>
#include <type_traits>
template < typename T,
typename = std::enable_if<std::is_integral<T> >::type >
void f(T t) {
printf("Integer function\n");
}
template void f(int i);
主要在下面...
#include "header.h"
int main(int argc, char** argv) {
int p = 3;
f(p);
}
它编译...没问题,但它没有显示 printf 的内容,我错过了什么?...
(我将 eclipse 用作 IDE,这可能是个问题?)
还有一件事......这个实现有意义吗? (我想根据输入的类型编写不同的代码,无论它是否是无符号的)。
template < typename T,
typename = std::enable_if<std::is_integral<T>::value>,
typename = std::enable_if<std::is_unsigned<T>::value>
>
void f(T t) {
printf("Unsigned f version.\n");
}
template < typename T,
typename = std::enable_if<std::is_integral<T>::value>,
typename = std::enable_if<std::is_signed<T>::value>
>
void f(T t) {
printf("Signed f version.\n");
}
在这种情况下它无法编译...那么如何处理呢?
谢谢
更新...
我尝试了第一个代码中建议的修改,它给了我以下错误
..\header.h:19:58: error: type/value mismatch at argument 1 in template parameter list for 'template<bool <anonymous>, class _Tp> struct std::enable_if'
typename = std::enable_if<std::is_integral<T> >::type >
^
..\header.h:19:58: error: expected a constant of type 'bool', got 'std::is_integral<_Tp>'
..\header.h:19:61: error: expected '>' before 'type'
typename = std::enable_if<std::is_integral<T> >::type >
^
..\main.cc: In function 'int main(int, char**)':
更新 2...
好的,伙计们...我一直在努力弄清楚它是什么我不明白...所以我正在研究 type_traits 的代码(所以我的目标是了解什么我做错了...)
我报告 enable_if 的代码(来自 type_traits)。
template<bool, typename _Tp = void>
struct enable_if //Lukkio decl. 1
{ };
// Partial specialization for true.
template<typename _Tp>
struct enable_if<true, _Tp> //Lukkio decl. 2
{ typedef _Tp type; };
因为我想了解像这样的一行会发生什么:
template<
typename T,
typename = std::enable_if<std::is_integral<T>::value>
>
void function(T t) {
printf("Is integral!\n");
}
所以假设 T
是固定的(比方说 int,它是整数),std::enable_if::value>
使用 decl。 1,但是假设 _Tp
是 void
类型那么实际上发生了什么,就减少而言(我现在用关键字 int
代替 T
... 应该是喜欢
template<
typename int,
typename = std::enable_if<std::is_integral<int>::value>
>
即
template<
typename int,
typename = std::enable_if<1>
>
所以我的问题是...第二个类型名称代表什么?
默认函数模板参数上的 SFINAE 并没有真正扩展。如果您想将单个重载限制为特定的 class 类型,则只能使用它。
对于非重叠的多重重载(比如你的 signed/unsigned 积分),你可以像这样在 return 类型上使用 SFINAE:
#include <cstdio>
#include <type_traits>
template < typename T>
auto f(T t)
-> std::enable_if_t<std::is_unsigned<T>::value && std::is_integral<T>::value>
{
printf("Unsigned f version.\n");
}
template < typename T>
auto f(T t)
-> std::enable_if_t<std::is_signed<T>::value && std::is_integral<T>::value>
{
printf("Signed f version.\n");
}
int main()
{
unsigned u = 1;
signed s = 1;
f(u);
f(s);
}
注意:enable_if_t<T>
是 typename enable_if<T>::type
的类型别名,在 C++14 中可用(您可以自己编写)
In this case it doesn't compile... so how to deal with this?
再次考虑您的模板:
template < typename T,
typename = std::enable_if<std::is_integral<T>::value>,
typename = std::enable_if<std::is_unsigned<T>::value>
>
void f(T t) {
您实际上并没有使用 SFINAE。您的未命名类型只是 std::enable_if<X>
。这始终是一个有效的类型。为了申请SFINAE,其实你需要在末尾加上::type
或者使用std::enable_if_t
,即:
template < typename T,
typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_unsigned<T>::value>
>
void f(T t) {
现在,您 运行 进入两个不明确的函数模板,您可以通过使用 enable_if_t
作为 值 而不是类型来消除歧义.即:
template < typename T,
std::enable_if_t<std::is_integral<T>::value &&
std::is_unsigned<T>::value>* = nullptr
>
void f(T t) { ... }
另一种情况也类似。
我在这里实现了这个功能(在单个头文件中)。
//header.h
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <iostream>
#include <stdint.h>
#include <type_traits>
template < typename T,
typename = std::enable_if<std::is_integral<T> >::type >
void f(T t) {
printf("Integer function\n");
}
template void f(int i);
主要在下面...
#include "header.h"
int main(int argc, char** argv) {
int p = 3;
f(p);
}
它编译...没问题,但它没有显示 printf 的内容,我错过了什么?... (我将 eclipse 用作 IDE,这可能是个问题?)
还有一件事......这个实现有意义吗? (我想根据输入的类型编写不同的代码,无论它是否是无符号的)。
template < typename T,
typename = std::enable_if<std::is_integral<T>::value>,
typename = std::enable_if<std::is_unsigned<T>::value>
>
void f(T t) {
printf("Unsigned f version.\n");
}
template < typename T,
typename = std::enable_if<std::is_integral<T>::value>,
typename = std::enable_if<std::is_signed<T>::value>
>
void f(T t) {
printf("Signed f version.\n");
}
在这种情况下它无法编译...那么如何处理呢?
谢谢
更新...
我尝试了第一个代码中建议的修改,它给了我以下错误
..\header.h:19:58: error: type/value mismatch at argument 1 in template parameter list for 'template<bool <anonymous>, class _Tp> struct std::enable_if'
typename = std::enable_if<std::is_integral<T> >::type >
^
..\header.h:19:58: error: expected a constant of type 'bool', got 'std::is_integral<_Tp>'
..\header.h:19:61: error: expected '>' before 'type'
typename = std::enable_if<std::is_integral<T> >::type >
^
..\main.cc: In function 'int main(int, char**)':
更新 2...
好的,伙计们...我一直在努力弄清楚它是什么我不明白...所以我正在研究 type_traits 的代码(所以我的目标是了解什么我做错了...)
我报告 enable_if 的代码(来自 type_traits)。
template<bool, typename _Tp = void>
struct enable_if //Lukkio decl. 1
{ };
// Partial specialization for true.
template<typename _Tp>
struct enable_if<true, _Tp> //Lukkio decl. 2
{ typedef _Tp type; };
因为我想了解像这样的一行会发生什么:
template<
typename T,
typename = std::enable_if<std::is_integral<T>::value>
>
void function(T t) {
printf("Is integral!\n");
}
所以假设 T
是固定的(比方说 int,它是整数),std::enable_if::value>
使用 decl。 1,但是假设 _Tp
是 void
类型那么实际上发生了什么,就减少而言(我现在用关键字 int
代替 T
... 应该是喜欢
template<
typename int,
typename = std::enable_if<std::is_integral<int>::value>
>
即
template<
typename int,
typename = std::enable_if<1>
>
所以我的问题是...第二个类型名称代表什么?
默认函数模板参数上的 SFINAE 并没有真正扩展。如果您想将单个重载限制为特定的 class 类型,则只能使用它。
对于非重叠的多重重载(比如你的 signed/unsigned 积分),你可以像这样在 return 类型上使用 SFINAE:
#include <cstdio>
#include <type_traits>
template < typename T>
auto f(T t)
-> std::enable_if_t<std::is_unsigned<T>::value && std::is_integral<T>::value>
{
printf("Unsigned f version.\n");
}
template < typename T>
auto f(T t)
-> std::enable_if_t<std::is_signed<T>::value && std::is_integral<T>::value>
{
printf("Signed f version.\n");
}
int main()
{
unsigned u = 1;
signed s = 1;
f(u);
f(s);
}
注意:enable_if_t<T>
是 typename enable_if<T>::type
的类型别名,在 C++14 中可用(您可以自己编写)
In this case it doesn't compile... so how to deal with this?
再次考虑您的模板:
template < typename T,
typename = std::enable_if<std::is_integral<T>::value>,
typename = std::enable_if<std::is_unsigned<T>::value>
>
void f(T t) {
您实际上并没有使用 SFINAE。您的未命名类型只是 std::enable_if<X>
。这始终是一个有效的类型。为了申请SFINAE,其实你需要在末尾加上::type
或者使用std::enable_if_t
,即:
template < typename T,
typename = std::enable_if_t<std::is_integral<T>::value>,
typename = std::enable_if_t<std::is_unsigned<T>::value>
>
void f(T t) {
现在,您 运行 进入两个不明确的函数模板,您可以通过使用 enable_if_t
作为 值 而不是类型来消除歧义.即:
template < typename T,
std::enable_if_t<std::is_integral<T>::value &&
std::is_unsigned<T>::value>* = nullptr
>
void f(T t) { ... }
另一种情况也类似。