Возврат ссылки на родительский класс C

#c

#c

Вопрос:

Я экспериментировал со структурой данных, подобной кортежу. Он должен содержать только 1 объект каждого типа, и каждый объект должен быть модулем в стиле C. Он использует причудливый способ доступа к объектам, которые он содержит, где он возвращает ссылку на класс, от которого он происходит. Нравится:

 template<class... Ts>
class Container : private Ts... 
{
public:
    template<class T>
    Tamp; get_component() 
    {   //returns reference to base class specified by T
        return static_cast<Tamp;>(* const_cast<Container<Ts...> *>(this));
    }
};
  

И предназначен для использования следующим образом:

 struct A { int   x, y; };
struct B { float x, y; };

int main() 
{
    using namespace std;

    Container<A, B> foo;
    Aamp; a_ref = foo.get_component<A>();

    a_ref.x = 5;
    a_ref.y = 10;

    const Bamp; b_ref = foo.get_component<B>();

    cout << b_ref.x << endl;
    cout << b_ref.y << endl;
}
  

Метод, который я использую, должен const_cast this , затем разыменовать его, а затем static_casts его в Tamp; . Есть ли какие-либо подводные камни в технике, которую я использую? В тестах, которые я запускал, этот дизайн, похоже, работает так, как ожидалось.

Редактировать: const_cast является избыточным. У меня было неправильное представление о назначении ссылки на указатель this . Я должен просто быть static_casting Tamp; к разыменованному this .

Комментарии:

1. Почему вы используете const_cast в первую очередь? Вы просто приводите к тому же типу.

2. Если вы хотите добавить const , вы можете использовать static_cast

3. @krzaq Или вы просто меняете возвращаемый тип на const Tamp; и тоже создаете функцию const

4. Вы правы, у меня нет причин быть const_casting . У меня было неправильное представление о назначении ссылок на это.

Ответ №1:

Насколько я могу судить, это можно упростить до просто:

 template<class... Ts>
class Container : private Ts... 
{
public:
    template<class T>
    Tamp; get_component() 
    {
        return *this;
    }

    template<class T>
    const Tamp; get_component() const
    {
        return *this;
    }
};
  

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

Одной из возможных проблем с кодом является многократное вхождение одного и того же базового типа, например:

 struct A {};
struct B : A {};

Container<A,B> container;
autoamp; a_ref = container.get_component<A>();
  

Это выдает ошибку. Вы можете избежать чего-то подобного, используя частные элементы данных вместо частных баз, что позволило get_component бы работать только с непосредственными базами.

Комментарии:

1. Одна из причин заключается в разрешении двусмысленностей, говоря, что foo.x неоднозначен, потому что и A, и B имеют член x.

2. @Brian: Если бы вы использовали общедоступные базы, то вы могли бы просто использовать Aamp; a_ref = foo; и get_component были бы ненужными.