模板成员函数签名与非模板成员函数签名冲突
template member function signature conflicts to non-template member function signature
我最近在为学习目的实现我自己的 Vector 容器时遇到了一个问题。
在我的Vector class中声明了一个非模板成员函数和一个同名的模板成员函数(插入函数)。如果发生冲突(当某些模板特化与非模板函数签名完全匹配时),编译器会给我错误....
假设我的向量 class 有 2 个称为插入的函数:
/* Vec.h */
template <class T> class Vec {
public:
iterator insert ( iterator position, size_type n, const value_type& val );
template <class InputIterator>
iterator insert (iterator position, InputIterator first, InputIterator last);
}
#include "Vec.hpp"
在Vec.hpp中:
/* Vec.hpp */
template <class T>
typename Vec<T>::iterator Vec<T>::insert( iterator position,
size_type n,
const value_type& val)
{
/* Implementation */
}
template <class T> template <class InputIterator>
typename Vec<T>::iterator Vec<T>::insert( iterator position,
InputIterator first,
InputIterator last )
{
/* Some code ... */
/* Copy the element */
while( first != last )
{
new ( position + idx ) T(*first);
++idx;
++first;
}
/* Some other code ... */
}
在main.cpp中:
int main()
{
Vec<int> myVec;
MyVec.push_back(5);
myVec.insert( myVec.begin(), 3, 3);
}
编译器错误:
../Vec.hpp: In instantiation of ‘T* Vec<T>::insert(Vec<T>::iterator, InputIterator, InputIterator) [with InputIterator = int; T = int;
Vec<T>::iterator = int*]’:
../main.cpp:128:45: required from here
../Vec.hpp:306:30: error: invalid type argument of unary ‘*’ (have ‘int’)
new ( position + idx ) T(*first);
^
编译器似乎试图使用模板插入函数而不是非模板插入函数。这与我的想法是矛盾的。看起来虽然我没有提供插入函数的参数列表:
myVec.insert<int*>
编译器隐式实例化了int类型的模板插入函数。
在cppreference的member templates中,也说编译器应该在这种情况下使用非模板。(请参考成员函数模板部分)
我的环境:Ubuntu 16.04 LTS, g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
请
解释为什么编译器使用模板成员函数
提供上述问题的解决方案。这样当我执行 insert(iterator, int, int) 或其他类似的函数调用时,例如 insert(iterator, unsigned int/long, unsigned int/long),它会调用正确的成员函数。
感谢大家的帮助。非常感谢!!
myVec.insert( myVec.begin(), 3, 3);
首先发生的事情是找到所有可能的重载:
iterator insert ( iterator position, size_type n, const value_type& val );
template <class InputIterator>
iterator insert (iterator position, InputIterator first, InputIterator last);
然后它进行模板参数推导。在这种情况下,InputIterator=int
有效。
iterator insert ( iterator position, size_type n, const int& val );
template <>
iterator insert (iterator position, int first, int last);
因为 3
和 3
都是 int
.
类型
现在可以进行 ocerload 解析。这里的模板函数转换为零。 non-template 需要将 int
转换为 size_type
.
转化次数为零的获胜。如果他们 并列 ,则 non-template 函数获胜;但零转化获胜。
注意迭代器类型是int
不是int*
;这会导致正文无法编译,因为 int
无法取消引用。
我最近在为学习目的实现我自己的 Vector 容器时遇到了一个问题。
在我的Vector class中声明了一个非模板成员函数和一个同名的模板成员函数(插入函数)。如果发生冲突(当某些模板特化与非模板函数签名完全匹配时),编译器会给我错误....
假设我的向量 class 有 2 个称为插入的函数:
/* Vec.h */
template <class T> class Vec {
public:
iterator insert ( iterator position, size_type n, const value_type& val );
template <class InputIterator>
iterator insert (iterator position, InputIterator first, InputIterator last);
}
#include "Vec.hpp"
在Vec.hpp中:
/* Vec.hpp */
template <class T>
typename Vec<T>::iterator Vec<T>::insert( iterator position,
size_type n,
const value_type& val)
{
/* Implementation */
}
template <class T> template <class InputIterator>
typename Vec<T>::iterator Vec<T>::insert( iterator position,
InputIterator first,
InputIterator last )
{
/* Some code ... */
/* Copy the element */
while( first != last )
{
new ( position + idx ) T(*first);
++idx;
++first;
}
/* Some other code ... */
}
在main.cpp中:
int main()
{
Vec<int> myVec;
MyVec.push_back(5);
myVec.insert( myVec.begin(), 3, 3);
}
编译器错误:
../Vec.hpp: In instantiation of ‘T* Vec<T>::insert(Vec<T>::iterator, InputIterator, InputIterator) [with InputIterator = int; T = int;
Vec<T>::iterator = int*]’:
../main.cpp:128:45: required from here
../Vec.hpp:306:30: error: invalid type argument of unary ‘*’ (have ‘int’)
new ( position + idx ) T(*first);
^
编译器似乎试图使用模板插入函数而不是非模板插入函数。这与我的想法是矛盾的。看起来虽然我没有提供插入函数的参数列表:
myVec.insert<int*>
编译器隐式实例化了int类型的模板插入函数。
在cppreference的member templates中,也说编译器应该在这种情况下使用非模板。(请参考成员函数模板部分)
我的环境:Ubuntu 16.04 LTS, g++ (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609
请
解释为什么编译器使用模板成员函数
提供上述问题的解决方案。这样当我执行 insert(iterator, int, int) 或其他类似的函数调用时,例如 insert(iterator, unsigned int/long, unsigned int/long),它会调用正确的成员函数。
感谢大家的帮助。非常感谢!!
myVec.insert( myVec.begin(), 3, 3);
首先发生的事情是找到所有可能的重载:
iterator insert ( iterator position, size_type n, const value_type& val );
template <class InputIterator>
iterator insert (iterator position, InputIterator first, InputIterator last);
然后它进行模板参数推导。在这种情况下,InputIterator=int
有效。
iterator insert ( iterator position, size_type n, const int& val );
template <>
iterator insert (iterator position, int first, int last);
因为 3
和 3
都是 int
.
现在可以进行 ocerload 解析。这里的模板函数转换为零。 non-template 需要将 int
转换为 size_type
.
转化次数为零的获胜。如果他们 并列 ,则 non-template 函数获胜;但零转化获胜。
注意迭代器类型是int
不是int*
;这会导致正文无法编译,因为 int
无法取消引用。