#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
были бы ненужными.