Souleymane
Souleymane

Reputation: 13

How to Delete specific template specialization with keyword delete in C++

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

Answers (3)

Ali Ramezani
Ali Ramezani

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

MadScientist
MadScientist

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

super
super

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

Related Questions