Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent constructor from casting argument types in c++?

I have a class to store big unsigned numbers and I'd like to allow user to create object using types such as long long, int, unsigned int and so on and also from string . I created a constructor BigNumber(const unsigned long long) and BigNumber(const std::string) but I want to disallow user to use constructions like: BigNumber('a') or BigNumber(true). I heard about explicit so I decided to write in my class definition following lines:

explicit BigNumber(const bool) = delete; explicit BigNumber(const char) = delete;

Unfortunately when I want to create object like: BigNumber x(1) or BigNumber("1234") I get error that call of overloaded constructor is ambiguous. I didn't get this message before I wrote these lines with explicit. How to solve this problem?

like image 527
wisniak Avatar asked Nov 23 '15 15:11

wisniak


2 Answers

You can achieve this using a template:

template<typename T,
         typename = typename std::enable_if<
            std::is_integral<T>::value
            && !std::is_same<char, T>::value
            && !std::is_same<bool, T>::value>::type>
explicit BigNumber(T const n);

This constructor can't be called with bools or chars.

like image 123
Simple Avatar answered Sep 21 '22 09:09

Simple


You can use a similar trick as when making classes non-copyable.

struct A {
  explicit A(int) { ... }
  explicit A(std::string) { ... }

  // prevent any other types
  template <typename T> A(T) = delete;
};

This will require the argument to A's constructor to be exactly int or string.

A a1{1};                      // OK
A a2{std::string("foobar")};  // OK
A a3(1L);                     // Error: use of deleted function 'A::A(T) [with T = long int]'
like image 39
Arvid Avatar answered Sep 18 '22 09:09

Arvid