I want to use new C++11 feature 'extern template class' with STL-container of movable objects (NOT copyable) and get compiler errors.
Example:
MyFile.hpp
#pragma once
#include <cstdio>
class MyFile
{
std::FILE * handle;
public:
MyFile(const char * filename);
~MyFile();
MyFile(MyFile && that);
MyFile & operator=(MyFile && that);
MyFile(const MyFile&) = delete;
void operator=(const MyFile&) = delete;
std::FILE const * getFile() const;
};
MyFile.cpp
:
#include "MyFile.hpp"
#include <iostream>
MyFile::MyFile(const char * filename)
: handle{nullptr}
{
if (!(handle = fopen(filename, "r")))
throw std::runtime_error("blah blah blah");
}
MyFile::~MyFile()
{
std::cout << "File::~File()" << std::endl;
if (handle)
fclose(handle);
}
MyFile::MyFile(MyFile && that)
: handle{nullptr}
{
*this = std::move(that);
}
MyFile & MyFile::operator =(MyFile && that)
{
std::swap(handle, that.handle);
return *this;
}
const std::FILE * MyFile::getFile() const
{
return handle;
}
FileDeque.hpp
:
#pragma once
#include <deque>
#include "MyFile.hpp"
extern template class std::deque<MyFile>;
using FileDeque = std::deque<MyFile>;
FileDeque.cpp
:
#include "FileDeque.hpp"
template class std::deque<MyFile>;
And the test program: #include
using namespace std;
#include "MyFile.hpp"
#include "FileDeque.hpp"
int main()
{
cout << "Hello World!" << endl;
{
FileDeque files;
files.emplace_back("C:/eula.1028.txt");
files.emplace_back("C:/eula.1031.txt");
files.emplace_back("C:/eula.2052.txt");
}
return 0;
}
With Visual Studio 2013 I get the following error:
D:\WinPrograms\Microsoft Visual Studio 12.0\VC\INCLUDE\deque(1714) : error C2280: 'MyFile::MyFile(const MyFile &)' : attempting to reference a deleted function
d:\devel\unique_ptr3\MyFile.hpp(18) : see declaration of 'MyFile::MyFile'
D:\WinPrograms\Microsoft Visual Studio 12.0\VC\INCLUDE\deque(1682) : while compiling class template member function 'void std::deque>::_Insert_n(std::_Deque_const_iterator>>,unsigned int,const MyFile &)' with [ _Ty=MyFile ]
D:\WinPrograms\Microsoft Visual Studio 12.0\VC\INCLUDE\deque(1510) : see reference to function template instantiation 'void std::deque>::_Insert_n(std::_Deque_const_iterator>>,unsigned int,const MyFile &)' being compiled with [ _Ty=MyFile ]
d:\devel\unique_ptr3\FileDeque.hpp(7) : see reference to class template instantiation 'std::deque>' being compiled with [ _Ty=MyFile ]
Generating Code...
It is clear that compiler tries to instantiate std::deque>::_Insert_n function that uses copying of objects, but why?
If std::deque is used directly in main.cpp I get no errrors:
#include <iostream>
#include <deque>
using namespace std;
#include "MyFile.hpp"
using FileDeque = std::deque<MyFile>;
int main()
{
cout << "Hello World!" << endl;
{
FileDeque files;
files.emplace_back("C:/eula.1028.txt");
files.emplace_back("C:/eula.1031.txt");
files.emplace_back("C:/eula.2052.txt");
}
return 0;
}
Also tried with clang and gcc and get similiar errrors.
So my questions:
- Is it possible to make compiler not to instantiate container's class of movable objects? Why compiler tryies to instantiate methods that require copying support?
- Do I want something wrong?
template class std::deque<MyFile>;
to your second variant of main function. In fact the internal function_Insert_n
uses a copy constructor, I think. It does not appear in the second case because implicit instantiation does not instantiate all class template members (only those which are really used). – Constructor