Reputation: 63
I'm trying to write own Smart Pointers (C++11) and stacks with one problem, that can be explained by next example:
#include <iostream>
template<typename T_Type>
class TestTemplateClass {
private:
T_Type _state;
public:
TestTemplateClass() : _state() {
std::cout << "Default constructor" << std::endl;
}
TestTemplateClass(int inState) : _state(inState) {
std::cout << "State constructor" << std::endl;
}
template<typename T_OtherType>
TestTemplateClass(const TestTemplateClass<T_OtherType> &inValue) {
std::cout << "Template-copy constructor" << std::endl;
}
template<typename T_OtherType>
void operator = (const TestTemplateClass<T_OtherType> &inValue) {
std::cout << "Operator" << std::endl;
}
~TestTemplateClass() {
std::cout << "Destructor" << std::endl;
}
};
TestTemplateClass<int> createFunction() {
return TestTemplateClass<int>();
}
int main() {
TestTemplateClass<int> theReference = createFunction();
std::cout << "Finished" << std::endl;
return 0;
}
output:
Default constructor
Destructor
Destructor
Finished
Destructor
As you can see, there are to many destructors here. In my mind, it's some problem with interaction between copy elision and template-constructor, but I don't know what may be the reason of such bug. I tried to fix the problem by adding explicit
copy-constructor and force compiler use my template-constructor:
// After TestTemplateClass(int inState), but it's not important
explicit TestTemplateClass(const OwnType &inValue) {
std::cout << "Copy constructor" << std::endl;
}
got next output:
Default constructor
Template-copy constructor
Destructor
Template-copy constructor
Destructor
Finished
Destructor
Here all looks good, but it doesn't look like a clean solution. Are there better alternatives?
Upvotes: 3
Views: 278
Reputation: 171127
(N)RVO can never introduce a discrepancy between the number of constructor and destructor calls. It's designed to make that principally impossible.
The problem is with your code. According to the rules of the language, a constructor template is never used to produce a copy constructor. The copy constructor is never a template, period.
So your class template does not actually declare a copy constructor, hence the compiler generates the default one (which of course doesn't print anything). If you need any special processing in the copy constructor, you must always declare it manually. A template will never be used to instantiate one.
Upvotes: 5
Reputation:
Your experiment suggests there isn't a bug at all: the first version simply used the copy constructor which doesn't print anything, and the second version uses a different constructor instead because you effectively disabled it.
(it also looks like whatever compiler and options you're using doesn't do RVO)
Upvotes: 2