Константная корректность C ++ / недостающий конструктор const для класса, поддерживающего как константные, так и неконстантные экземпляры - PullRequest
0 голосов
/ 17 января 2020

У меня есть несколько связанных классов, как в следующем примере, где я хочу, чтобы они поддерживали экземпляры не-const и const (как в функции x):

#include <vector>

class Original;

class View
{
public:
    View(Original *that) : m(that) {}
    Original * m;
};

class Original
{
public:
    auto columns() {return View(this);}
    //~ const auto columns() const {return View(this);} // comment #1
    std::vector<int> m;
};

void x()
{
    Original o1;
    const Original o2;
    //~ o2.columns(); // comment #2
}

Я компилирую это с g++ -std=gnu++17 -c const.cpp и получим следующие результаты:

case 1: точно так же, как и выше: компилируется просто отлично (что уже озадачивает меня в свете того, что в случае 2 ниже я просто добавляю вызов, и он не удастся ...)

case 2: раскомментируйте # 2, и мы получим ...

const.cpp: In function 'void x()':
const.cpp:24:13: error: passing 'const Original' as 'this' argument discards qualifiers [-fpermissive]
  o2.columns(); // comment #2
             ^
const.cpp:15:7: note:   in call to 'auto Original::columns()'
  auto columns() {return View(this);}
       ^~~~~~~

case 3: кроме того, раскомментируем # 1; который дает ...

const.cpp: In member function 'const auto Original::columns() const':
const.cpp:16:46: error: invalid conversion from 'const Original*' to 'Original*' [-fpermissive]
  const auto columns() const {return View(this);} // comment #1
                                              ^
const.cpp:8:2: note:   initializing argument 1 of 'View::View(Original*)'
  View(Original *that) : m(that) {}
  ^~~~

Мне кажется, мне нужен конструктор для создания объекта const, который недоступен в C ++. Поэтому я попытался сделать View шаблонным классом для поддержки как константного, так и неконстантного члена m. Но я не сразу запустил его, и в любом случае он кажется довольно уродливым.

Кто-нибудь намекает? Большое спасибо уже!

Ответы [ 3 ]

0 голосов
/ 18 января 2020

попробуйте const пару

#include <vector>

class Original;

class View{
public:
    View(Original *that) : m(that) {}     // miss the return needed
    Original * m;
};

class Original
{
public:
   auto columns() const {     // ADDED for pair
   return View(this);          // the return needed
}

   auto columns() const {return View(this);} // comment #1  //REMOVED in return i guess no use
    std::vector<int> m;
};

void x()
{
    const Original o1;            // ADDED for pair
    const Original o2;
    o2.columns(); // comment #2
}
0 голосов
/ 19 января 2020

Это то, что я придумал сегодня, но на основе шаблонов (что я считаю довольно уродливым); поддерживает как постоянное, так и неконстантное использование (как в функции x):

#include <vector>

class Original;

template<class T>
class View
{
public:
    View(T *that) : m(that) {}
    T * m;
};

class Original
{
public:
    auto columns() {return View(this);}
    const auto columns() const {return View(this);}
    std::vector<int> m;
};

void x()
{
    Original o1;
    const Original o2;
    o2.columns();
}
0 голосов
/ 17 января 2020

Ваш конструктор View принимает указатель Original, но вы пытаетесь передать ему указатель на const Original! Вам нужен конструктор (и переменная-член), чтобы отразить это:

class View
{
public:
    View(const Original *that) : m(that) {}
    const Original * m;
};

Смотрите его здесь: https://ideone.com/nEgFxD

Однако, если вы в порядке с Принимая удар для создания глубоких копий, еще лучше было бы вообще избегать бизнеса с указателями:

//Declare Original out so View can use its copy/move constructor
class Original
{
public:
    auto columns();
    const auto columns() const;
    std::vector<int> m;
};

//Full declaration/implementation of View
class View
{
public:
    View(const Original &that) : m(that) { }
    Original m;
};

//Now that View's constructors are defined, implement these Original funcs
auto Original::columns() {return View(*this);}
const auto Original::columns() const {return View(*this);} // comment #1

int main()
{
    Original o1;
    const Original o2;
    o2.columns(); // comment #2
}

Смотрите его здесь: https://ideone.com/HnpQ38

...