Reputation: 13
I am trying to understand some use cases of the keyword delete in C++11.
So I tried to delete a specific class template specialization by deleting its constructor in the main method.
Here is my code :
using namespace std;
template <typename T>
class ComplexNumber
{
T x;
T y;
public:
ComplexNumber(T a, T b) : x(a) , y(b) {}
void display() { std::cout<<x << " + i"<<y<<std::endl; }
};
int main()
{
ComplexNumber(char a, char b) = delete;
ComplexNumber<int> obj1(1,2);
ComplexNumber<double> obj2(1.0,2.0);
ComplexNumber<char> obj3('1' , '2');
return 0;
}
But the program execution doesn't block on "ComplexNumber obj3('1' , '2')" as expected, but on the line "ComplexNumber(char a, char b) = delete".
Here is errors' trace:
main.cpp: In function ‘int main()’:
main.cpp:28:18: error: missing template arguments before ‘(’ token
ComplexNumber(char a, char b) = delete;
^
main.cpp:28:19: error: expected primary-expression before ‘char’
ComplexNumber(char a, char b) = delete;
^~~~
main.cpp:28:27: error: expected primary-expression before ‘char’
ComplexNumber(char a, char b) = delete;
^~~~
main.cpp:28:43: error: expected primary-expression before ‘;’ token
ComplexNumber(char a, char b) = delete;
Could you help to understand why we cannot delete a specific constructor "for char type" here?
Upvotes: 1
Views: 4546
Reputation: 49
I think you were trying to do this:
#include <iostream>
using namespace std;
template <typename T>
class ComplexNumber
{
T x;
T y;
public:
ComplexNumber(T a, T b) : x(a) , y(b) {}
void display() { std::cout<<x << " + i"<<y<<std::endl; }
};
template<> ComplexNumber<char>::ComplexNumber(char a, char b) = delete;//<== the right way to delete
int main()
{
ComplexNumber<int> obj1(1,2);
ComplexNumber<double> obj2(1.0,2.0);
ComplexNumber<char> obj3('1' , '2');
return 0;
}
which will ends up to
main.cpp: In function ‘int main()’: main.cpp:19:39: error: use of deleted function ‘ComplexNumber::ComplexNumber(T, T) [with T = char]’
ComplexNumber<char> obj3('1' , '2');
^ main.cpp:13:12:
note: declared here template<> ComplexNumber<char>::ComplexNumber(char a, char b) = delete;
You can test it here
Upvotes: 1
Reputation: 3460
What effect do you want to achieve?
The user gets an error message when trying to instantiate your class with char
. Here I would use a static_assert
with a useful message:
template <typename T>
class ComplexNumber
{
static_assert(!std::is_same_v<char, T>,
"char is not allowed because .... consider using ??? instead.");
// ...
};
Usually you want to = delete
one (or more) of your constructors when the constructor itself is a function template:
class MyComplexNumber
{
double _re;
double _im;
public:
template <typename T>
MyComplexNumber(T re, T im) : _re(re), _im(im) { }
MyComplexNumber(char, char) = delete;
};
Upvotes: 3
Reputation: 12968
The more idiomatic way of putting a constraint on your template is to use static_assert
.
#include <iostream>
using namespace std;
template <typename T>
class ComplexNumber
{
static_assert(!std::is_same_v<T, char>);
T x;
T y;
public:
ComplexNumber(T a, T b) : x(a) , y(b) {}
void display() { std::cout<<x << " + i"<<y<<std::endl; }
};
int main()
{
ComplexNumber<int> obj1(1,2);
ComplexNumber<double> obj2(1.0,2.0);
ComplexNumber<char> obj3('1' , '2');
return 0;
}
Upvotes: 1