C++ c++;向模板传递某些参数时会发生奇怪的链接器错误

C++ c++;向模板传递某些参数时会发生奇怪的链接器错误,c++,c++11,vector,linker,C++,C++11,Vector,Linker,我一直在尝试自己实现std::vector。我遇到了一个奇怪的链接器问题,当我将一些参数传递给模板时会出现这个问题。当与其他参数一起传递时,代码工作正常。我真的很困惑这里出了什么问题,不知道我可以用什么关键字来搜索。问题描述如下: //vector.hpp: all the following is inside namespace wyf template<typename Tp, typename Allocator = std::allocator<Tp>> cla

我一直在尝试自己实现std::vector。我遇到了一个奇怪的链接器问题,当我将一些参数传递给模板时会出现这个问题。当与其他参数一起传递时,代码工作正常。我真的很困惑这里出了什么问题,不知道我可以用什么关键字来搜索。问题描述如下:

//vector.hpp: all the following is inside namespace wyf
template<typename Tp, typename Allocator = std::allocator<Tp>>
class vector {
public:
    using value_type = Tp;
    using allocator_type = Allocator;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using reference = value_type&;
    using const_reference = const value_type&;
    using pointer = typename std::allocator_traits<Allocator>::pointer;
    using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
// linker error occurs when calling this ctor with certain arguments
    vector(size_type n, const_reference val, const allocator_type& alloc = allocator_type());
// other ctors
    vector() : begin_(nullptr), end_(nullptr), capacity_() { }
    vector(size_type n, const_reference val, const allocator_type& alloc = allocator_type());
    explicit vector(size_type n);
    template<typename IterTp> 
      vector(IterTp beg_, IterTp end_, const allocator_type& alloc = allocator_type());
    vector(const vector& other, const allocator_type& alloc = allocator_type());
    vector(vector&& other);
    vector(vector&& other, const allocator_type& alloc);
    vector(std::initializer_list<value_type> init_list, const allocator_type& alloc = allocator_type());
// omitting other member functions.
private: // three data members to hold the objects and raw memory
    pointer begin_; // using pointer = value_type*;
    pointer end_;
// Empty Base Optimization Helper class to hold both Allocator and capacity_
    EmptyBaseOptimizationHelper<allocator_type> capacity_; 
}
// still in vector.hpp, the implemention goes below
template<typename Tp, typename Allocator> 
vector<Tp, Allocator>::vector(std::size_t n, const Tp& val, const Allocator& alloc) :
begin_(nullptr), end_(nullptr), capacity_(nullptr, alloc) {
  begin_ = (get a pointer to allocator)->allocate(n*2);// allocate raw memory
  end_ = begin_ + n;
  capacity_.capacity_ = begin_ + n*2; 
  for (auto p = begin_; p != end_;) 
    (get a pointer to allocator)->construct(p++, val);
 }

//vector.hpp:以下所有内容都在命名空间wyf中
模板
类向量{
公众:
使用值_type=Tp;
使用分配器类型=分配器;
使用size\u type=std::size\u t;
使用差分类型=std::ptrdiff\t;
使用引用=值\类型&;
使用const_reference=const value_type&;
使用pointer=typename std::allocator\u traits::pointer;
使用const\u pointer=typename std::allocator\u traits::const\u pointer;
//使用某些参数调用此连接器时发生链接器错误
向量(size_type n,const_reference val,const allocator_type&alloc=allocator_type());
//其他部门
向量():开始(nullptr),结束(nullptr),容量{
向量(size_type n,const_reference val,const allocator_type&alloc=allocator_type());
显式向量(大小\类型n);
模板
向量(IterTp beg、IterTp end、常量分配器类型&alloc=分配器类型();
向量(const vector和other,const allocator_type&alloc=allocator_type());
向量(向量和其他);
向量(向量和其他,常量分配器类型和alloc);
vector(std::initializer\u list init\u list,const allocator\u type&alloc=allocator\u type());
//省略其他成员函数。
private://三个数据成员,用于保存对象和原始内存
指针开始\;//使用指针=值\类型*;
指针端;
//空的基本优化帮助器类,用于同时容纳分配器和容量_
清空BaseOptimizationHelper容量;
}
//仍然在vector.hpp中,实现如下
模板
向量::向量(std::size\u t n、常量Tp和val、常量分配器和alloc):
开始(nullptr)、结束(nullptr)、容量(nullptr、alloc){
begin=(获取指向分配器的指针)->allocate(n*2);//分配原始内存
结束=开始+n;
容量容量=开始容量+n*2;
对于(自动p=开始p!=结束)
(获取指向分配器的指针)->construct(p++,val);
}
这就是vector.hpp的全部内容(我使用了一些伪代码使其更具可读性)。当我做一些测试时,奇怪的链接器错误出现了

#include "vector.hpp"
int main() { 
  wyf::vector<int> v2(10, 20);
}
#包括“vector.hpp”
int main(){
矢量v2(10,20);
}
当我使用g++/clang++编译时,会弹出以下链接器错误:

vector.cc:(.text+0x66): undefined reference to `wyf::vector<int, std::allocator<int> >::vector<int>(int, int, std::allocator<int> const&)'
vector.cc:(.text+0x66):对“wyf::vector::vector(int,int,std::allocator const&)”的未定义引用
似乎wyf::vector v2(10,20);被视为调用具有签名wyf::vector(int,int,std::allocator const&)的ctor。但我声明和实现的是wyf::vector(std::size\u t,const int&,std::allocator const&)。当我试图链接一些我没有真正实现的东西时,链接器被设计成失败。因此出现了链接器错误。 考虑到这些,我试着打了以下电话

wyf::vector<int> v3(static_cast<std::size_t>(10), 20);
wyf::vector v3(静态_cast(10),20);
而且效果很好。此外,我发现,只要我传递将触发转换(隐式或显式)的参数,链接器就不会抱怨:

wyf::vector<int> v4(10.0, 20);
wyf::vector<int> v5(10, 20.0);
wyf::vector v4(10.0,20); 矢量v5(10,20.0);
上面的代码编译和链接没有错误。我真的很困惑。有谁能告诉我为什么会发生这些事情,以及我能做些什么使wyf::vector v(10,20)按预期工作。

当我试图重现问题时,我发现了问题所在。 这里的问题是构造函数重载解决方案选择尚未实现的构造函数

wyf::vector<int> v1(10, 20);
但相反,编译器会看到更好的匹配,并选择:

template<typename IterTp> 
vector(IterTp beg_, IterTp end_, const allocator_type& alloc = allocator_type());
模板
向量(IterTp beg、IterTp end、常量分配器类型&alloc=分配器类型();
并实例化wyf::vector(int,int,const std::allocator&),IterTp为int。由于我还没有实现该构造函数,代码可以编译,但链接失败。以下代码成功链接:

wyf::vector<int> v3(static_cast<std::size_t>(10), 20);
wyf::vector<int> v4(10.0, 20);
wyf::vector<int> v5(10, 20.0);
wyf::vector v3(静态_cast(10),20);
矢量v4(10.0,20);
矢量v5(10,20.0);

因为这两种极光有两种不同的类型。因此,编译器无法推断模板版本构造函数的IterTp类型,而选择了非模板版本,这是我所期望的代码。

“以下所有内容都在命名空间wyf中”请发布所有代码,而不是解释省略代码中内容的注释。另外,请缩进你的代码。你使用哪种编译器?您出于某种原因禁用了隐式转换。传递给构造函数的文本
10
是类型
int
这是正常的,而隐式转换应该应用于
std::size\t
。老实说,我使用GCC,我甚至不知道是否可以禁用隐式转换,我已经寻找了很久了。当它被强制为可编译的形式时。构造一个。你的工作是将其简化为一个可以在互联网上向陌生人显示的形式。如果整个代码太长,则生成一个较小的示例,显示相同的问题。通过逐步删除不相关的代码来做到这一点,但不要依靠猜测来找出相关的内容——如果你不知道问题出在哪里,很可能你会删除相关的内容。删除一个位,编译以查看是否出现相同的问题,等等。
wyf::vector<int> v3(static_cast<std::size_t>(10), 20);
wyf::vector<int> v4(10.0, 20);
wyf::vector<int> v5(10, 20.0);