未使用指针类型推导出模板类型
Template type not deduced using pointer type
我惊讶地发现T
无法在以下代码中成功推导:
template <typename T>
void Set(T* a,T b)
{
*a = b;
}
void Test()
{
unsigned long a;
Set(&a, 1);
}
VC++抱怨一个歧义:
1>test.cpp(10): error C2782: 'void Set(T *,T)' : template parameter 'T' is ambiguous
1> test.cpp(32) : see declaration of 'Set'
1> could be 'int'
1> or 'unsigned long'
显然,这可以通过将调用更改为Set(&a, 1ul);
来解决,但我的问题是为什么这是必要的?
为什么不能使用指针的类型来推导T
,而指针的类型应该是明确的?
有没有一种方法可以重写模板,使对Set
的原始调用能够成功编译?
为什么不能使用指针的类型来推导t,应该是毫不含糊的
因为你没有告诉编译器这样做。模板参数的推导不一致会导致推导失败。
有没有一种方法可以重写模板,使原始调用要Set编译成功吗?
是的,使用非推导上下文。
template <typename T>
struct identity {using type=T;};
template <typename T>
using identity_t = typename identity<T>::type;
template <typename T>
void Set(T* a, identity_t<T> b) {
*a = b;
}
演示
或者使用第二个模板参数。
参数T* a
和T b
都是推导出的上下文,因此首先编译器将尝试从这两个上下文中推导出T
,以使T*
与第一个参数的类型相同,T
和第二个参数的类型相等(遵循通常的衰减调整)。这将从第一个参数中产生unsigned long
,从第二个参数中得出int
,因此尝试推导失败。
然后编译器将尝试找到T
,使得第一个参数可转换为T*
,而第二个参数可转换至T
(而不是类型相同)。但是,在这种情况下,只考虑某些转换。参见N3936,中的[临时扣除呼叫]
(4) 通常,推导过程试图找到模板参数值,这些值将使推导出的
A
与CCD_ 16相同(在如上所述对类型CCD_。然而,有三种情况允许区别:(4.1)——如果原始
P
是引用类型,则推导出的A
(即引用引用的类型)可以是比变换后的CCD_ 20更符合cv。(4.2)-转换后的
A
可以是另一个指针或指向成员类型的指针,可以转换为通过资格转换推导出CCD_ 22(4.4)(4.3)-如果
P
是一个类,并且P
的形式为简单模板id,,则变换后的A
可以是推导出的CCD_ 26。同样,如果P
是指向简单模板id形式的类的指针,则转换后的A
可以是指向由推导的CCD_ 29所指向的派生类的指针。(5) 只有在类型推导失败的情况下,才会考虑这些备选方案。如果它们产生不止一个可能推导出的
A
,则类型推导失败。[注意:如果在函数模板的函数参数,或仅在非推导上下文中使用,其对应模板参数不能从函数调用中推导出来,并且模板参数-尾注]
对于推导上下文中的参数类型,不考虑整数转换,例如int
到unsigned long
。所以T
在这种情况下也不可能是unsigned long
。因此,T
的推导完全失败。
我的修复建议:
template <typename T, typename U>
void Set(T* a, U&& b)
{
*a = std::forward<U>(b);
}
这是不明确的,因为它可能既是
int*
和int
(因为1是int
)unsigned long*
和unsigned long
(因为您的指针是unsigned long*
)
值1被推导为类型int
,与&a
推导的模板参数不匹配。
有没有一种方法可以重写模板,使原始调用到Set将成功编译
双参数方式:(仅用于完整性)
#include <type_traits>
// SFINAE : in case S is not convertible to T
template <typename T, typename S,
typename std::enable_if<
std::is_convertible<S, T>::value>::type* = nullptr >
void Set(T *a, S b)
{
*a = b;
}
- 非类型指针和引用模板参数,以及在编译时如何/为什么解析它们.c++
- 如何访问在 c++ 中在类内声明的结构类型指针变量?
- (C )找到基本类型指针的儿童类型
- 表达式必须具有指向对象的指针类型(指针向量)
- 将子项复制构造到父类型指针中
- C 返回类型指针声明
- 调用虚拟函数而不通过类类型指针创建任何对象
- C++ 如何使用类类型指针制作向量
- 为什么基类型指针不能获取派生类对象的地址值?
- 如何在 C++ 中获取映射类型指针,映射
- 如何检查该类型的类型指针是正确对齐的
- 正在转换为短类型指针
- 指向任意类方法的模板非类型指针
- 如何通过强制转换类型指针将字符数组转换为uint16_t
- 指向shared_ptr的不透明类型 C 指针
- C++:从值类型指针强制转换为包含迭代器
- C/C++:访问给定类型指针的位置与访问另一类型指针的相同位置不同
- 比较类型指针
- 数据类型指针使用*(Datatype *)
- 如何打印c++中char类型指针的所有值