简体   繁体   中英

Differentiate between constructor with default argument value and empty argument list

In C++, is there any way to differentiate between a constructor with no argument and one with arguments that all have default values?

Like this:

class Object {
public:
      Object(int a = 0, int b = 0 ){
      }

      Object(){
      }
};

In addition, the compiler could not determine which constructors should be used in the following code sample:

Object obj;  // which one, Object(int,int) or Object()

Assuming the two c'tors are really exceptionally different (I suspect that's unlikely, since both supposedly create some "default state" for the object), you can do as the standard library does when it needs to disambiguate c'tors. You can make it work based of off tag dispatch:

class Object {
  public:
  enum class from_ints_t{};
  static constexpr from_ints_t from_ints{};

  Object(from_ints_t, int a = 0, int b = 0 ){
  }

  Object(){
  }
};

Now default constructing looks like Object obj; and constructing from the default values of those integers looks like Object obj{Object::from_ints}; . There's no ambiguity left.

Just for the fun, was trying to propose something like:

struct Object {
      // SFINAE
      template<class T,
               typename = typename std::enable_if<std::is_same<T, int>::value>::type>
      Object(T a = 0, T b = 0){
          std::cout << "ctor with two ints and defaults" << std::endl;
      }

      Object(){
          std::cout << "empty ctor" << std::endl;
      }
};

int main() {
    Object o1;
    Object o2(8, 9);
    Object o3<int>();    
}

But unfortunately the creation of o3 in that way is not allowed, as apparently you cannot explicitly specify template argument for a constructor, see: Can the template parameters of a constructor be explicitly specified? (answer is: no...)

Anyway, this was just for fun.

I found the answer by Scab in the comment above the most appropriate for the imagined need - use named ctor idiom - http://isocpp.org/wiki/faq/ctors#named-ctor-idiom :

struct Object {
    static Object emptyCtor() { return Object{}; }
    static Object defaultIntegers() { return Object{0, 0}; }
    static Object create(int a, int b) { return Object{a, b}; }
protected:
    Object(int a, int b){
      std::cout << "ctor with two ints" << std::endl;
    }

    Object(){
      std::cout << "empty ctor" << std::endl;
    }
};

int main() {
    Object o1 = Object::emptyCtor();
    Object o2 = Object::defaultIntegers();
    Object o3 = Object::create(8, 9);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM