Как определить преобразование из стандартного типа в пользовательский тип? - PullRequest
1 голос
/ 22 июня 2019

Я работаю над файлом C ++, который может выполнять кодирование Хаффмана, и столкнулся с небольшой проблемой при переходе от карты типа string и int к очереди типа Node, и мне было интересно, есть ли способчтобы определить явное преобразование из пары строк и целых чисел в Node.

В настоящее время у меня есть так, что карта преобразуется в вектор пар, а затем преобразуется в вектор типа Nodeзатем в очередь с приоритетами типа Node.

// this->char_freqs is of type map<std::string, int>
std::vector<std::pair<std::string, int> > my_vector(this->char_freqs.begin(), this->char_freqs.end());
  std::vector<Huffman::Node*> real_vector;
  for (unsigned int i = 0; i < my_vector.size(); ++i) {
    real_vector.push_back(new Huffman::Node(my_vector[i].first, my_vector[i].second));
  }
  std::priority_queue<Huffman::Node*, std::vector<Huffman::Node*>, Huffman::comp> PQ(real_vector.begin(), real_vector.end());

Я еще не проверял, будет ли это работать.Тем не менее, я больше стремлюсь разработать метод, который мог бы явно определить преобразование из pair<string, int> в Node*, чтобы переход от карты к очереди мог выполняться по существу в одну строку.Что-то вроде:

std::priority_queue<Huffman::Node*, std::vector<Huffman::Node*>, Huffman::comp> PQ(this->char_freqs.begin(), this->char_freqs.end());

При чтении документации я нашел только примеры преобразования пользовательских типов в типы по умолчанию, а не наоборот.

Редактирование 1

Надеюсь, это должно быть проще и объяснить, что я ищу.

class Node {
 public:
  char character;
  int frequency;
  Node(char char_, int val_) {
    character = char_;
    frequency = val_;
  }
  operator std::pair<char, int>() {
    return std::pair<char, int>(character, frequency);
  }
};
int main(int argc, char** argv) {
  std::vector<std::pair<char, int> > my_vector_1;
  Node n('a', 3);
  my_vector_1.push_back(n); // Can use a Node as an input since the conversion has been explicitly defined

  std::vector<Node> my_vector_2;
  std::pair<char, int> pair('a', 3);
  my_vector_2.push_back(pair); // Invalid
}

Конечно, неверный параметр потерпит неудачу, потому что компилятор не имеет способа конвертировать пару в узел, но можно ли заставить работать недопустимую строку?

Ответы [ 2 ]

2 голосов
/ 22 июня 2019

Если я правильно понимаю вашу проблему, вам нужен еще один конструктор для Node, что-то вроде этого

Node(const std::pair<char, int>& pair) : character{pair.first}, 
                                         frequency{pair.second} { }

Обратите внимание, что я использую список инициализаторов членов для инициализации данных вашего класса. Это рекомендуемый способ, см. Дополнительную информацию https://en.cppreference.com/w/cpp/language/initializer_list

В дальнейшем вы можете пометить конструктор как explicit, чтобы избежать нежелательных преобразований (см. Что означает явное ключевое слово? ), и использовать emplace_back вместо push_back, чтобы избежать построения временного https://en.cppreference.com/w/cpp/container/vector/emplace_back. Маркировка конструктора explicit может не соответствовать вашему варианту использования, выбор за вами. Если вы пометите конструктор explicit, push_back, как написано сейчас, перестанет работать, вам нужно будет явно создать Node или использовать emplace_back.

1 голос
/ 22 июня 2019

Проблема относится к Implicit conversion. Неявное преобразование определяется в терминах copy-initialization : if an object of type T can be copy-initialized with expression E, then E is implicitly convertible to T.Теперь рассмотрим следующий пример:

#include <iostream>
#include <utility>

class Point
{
public:
    Point():x(),y()
    {
    }

    Point( const std::pair< int, int>& pair):
        x( pair.first),
        y( pair.second)
    {

    }

    int getX() const
    {
        return x;
    }

    int getY() const
    {
        return y;
    }

private:
    int x;
    int y;
};

int main(int , char *[])
{
    Point p = std::pair< int, int>( 1, 2);
    std::cout<< "x = "<< p.getX()<< ", y = "<< p.getY()<< std::endl;

    return 0;
}

output x = 1, y = 2

Здесь std::pair< int, int> неявно преобразуется в тип Point.Еще один момент: если вы используете explicit с Point( const std::pair< int, int>& pair), то вы не можете использовать вышеуказанный синтаксис, в этом случае вы должны изменить его на Point p( std::pair< int, int>( 1, 2));Для получения дополнительной информации см. Следующую ссылку copy_initialization .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...