如何为第一对提供默认值?

时间:2014-04-02 17:50:21

标签: c++ constructor default std-pair

我正在使用一对类型:

typedef std::pair<int, std::string> Nomnom;

示例放置它的使用:

void DoIt(const Nomnom &toNom) { 
    ...
}
void DoItAgain(const Nomnom &toNomAgain) { 
    ...
}

在我的情况下,如果未指定,则为该对提供默认值是有意义的。也就是说,我希望能够做到这一点:

DoIt("Thisisit");
DoItAgain("Thisisit");

并且它等同于:

DoIt(NomNom(0, "Thisisit"));
DoItAgain(NomNom(0, "Thisisit"));

我希望每次使用Nomnom时都不要定义两个变体。

有没有办法完成为Nomnom而不是typedef定义一个类的缺点,提供一个arg构造函数,然后提供调用std::pair构造函数的zero-arg和two-arg构造函数?

3 个答案:

答案 0 :(得分:2)

原始问题

  

有没有办法完成为Nomnom定义一个类的缺点,提供一个arg构造函数,然后提供调用std :: pair构造函数的zero-arg和two-arg构造函数?

你可以有更多的构造函数重载

ClassNoms() : one(std::make_pair(-1,"") {}
ClassNoms(int id) : one(std::make_pair(id,"") {}
ClassNoms(const std::string& name) : one(std::make_pair(-1,name) {}
ClassNoms(int id, const std::string& name) : one(std::make_pair(id,name) {}

更新:

  

有没有办法完成为Nomnom而不是typedef定义一个类的缺点,提供一个arg构造函数,然后提供零arg和两个arg构造函数调用std::pair构造函数?

typedef std::pair<int, std::string> Nomnom;

您无法为typedef&d; NomNom提供默认构造函数,因为std::pair<>并未提供构造函数。要实现这一点,您需要从NomNom继承一个类std::pair<>,或者恕我直接为它提供一个包装器,并使用它:

template<typename First,typename Second>
struct DefaultValuedPair {
     std::pair<First,Second> value;
     First& first;
     Second& second;
     DefaultValuedPair
        ( const First& first = First()
        , const Second& second = Second()
        ) 
     : value(std::make_pair(first,second))
     , first(value.first)
     , second(value.second) {}
     DefaultValuedPair(const std::pair<First,Second>& rhs) 
     : value(rhs)
     , first(value.first)
     , second(value.second) {}
     // Add more implicit type conversions for std::pair<First,Second>
     // as necessary ...
};

并且

typedef DefaultValuedPair<int, std::string> Nomnom;

你可以有一个就像一个构造函数的函数,但它不能被命名并被称为NomNom(声明的)类型的纯等价,这就不会了#39; t优于使用std::make_pair()

建议的包装器解决方案可能会对重构使用NomNom的现有代码的注意事项产生巨大影响,并且应该与此类无缝协作。如上所述,只是替换/伪装std::make_pair本身,没有任何意义恕我直言。

答案 1 :(得分:2)

您无法轻松地将自己的构造函数添加到std::pair(继承它并不是一个真正的选项)。

但是你可以提供一个小函数来构造它并相应地重载它:

Nomnom nomnom(const std::string& s) { return Nomnom(-1, s); }
Nomnom nomnom(int i) { return Nomnom(i, ""); }

您还可以重载DoItDoItAgain并转发常规实现。

void DoIt(const Nomnom& n) { /* ... */ }
void DoIt(int i) { DoIt(Nomnom(i, "")); }

答案 2 :(得分:1)

如果您正在使用C ++ 11,则可以从与using配对继承构造函数。我认为这是解决问题的最简洁方法。

是否有理由(除了不想重新实现std::pair的构造函数之外)你不想从std :: pair继承?

#include <utility>
#include <string>
#include <iostream>

/**
 * Nomnom is just a std::pair with a customized constructor.
 */
class Nomnom : public std::pair <int, std::string> {
  typedef std::pair<int, std::string> parent_type; // For convenience

  public:
  using parent_type::parent_type; // Inherit Pair's constructors
  Nomnom (std::string S) : parent_type(0, S) {} // And add our own
  Nomnom (char const * S) : parent_type(0, S) {} // Handle C strings...
};

/**
 * Show that we can just use Nomnom as a std::pair...
 */
template <class FIRST, class SECOND> 
std::ostream & operator<< (std::ostream & out, std::pair <FIRST, SECOND> const & print_me) {
  return out << print_me.first << ", " << print_me.second << '\n';
}

/**
 * Use this to test initizlization while passing to a method
 */
void foo (Nomnom const & print_me) {
  std::cout << print_me;
}

int main (void) {
  std::cout << Nomnom("Hello!");
  std::cout << Nomnom(5, "World!");
  foo ("Mouse!");

  return 0;
}