#c #c 17 #template-meta-programming
Вопрос:
Я относительно новичок в TMP на c . Мне было интересно, есть ли способ реализовать контейнер для классов(а не его экземпляров!) в c (предпочтительно 17, без boost или c 20).
Ниже приведено то, что я ищу:
int integer = 0xDEADBEEF;
std::string hello ("hello");
boost::any c (integer);
const int c_deadbeef = integer;
intamp; cr_deadbeef (integer);
using oneClassContainer = decltype( makeClassContainer(integer, hello, c, c_deadbeef, cr_deadbeef) );
// classContainer<int, std::string, boost::any, const int, intamp;>
using anotherClassContainer = classContainer<int, const intamp;, const int>;
// anotherClassContainer is passed to a different function.
// in that function:
getType<anotherClassContainer,0> anotherInt = 3; //int
getType<anotherClassContainer,1> constIntRef (anotherInt); //const intamp;
getType<anotherClassContainer,2> constIntRef= 3; //const int
Я также хотел бы, чтобы постоянство сохранялось, когда classContainer создается с использованием makeClassContainer
аргументов функции. Например , const int b=3;
а затем make_tuple(b,1)
вызов возвращает a tuple<int,int>
— const
пропал без вести, и поэтому использование make_tuple
, в любом случае, здесь не вариант. (На самом деле, если бы мы могли каким-то образом сохранить const
квалификацию и volatile
make_tuple
, это было бы идеальным решением)
Итак, подводя итог, мой вопрос заключается в том, возможно ли реализовать следующее:
- структура, которая содержит классы (не обязательно их экземпляры), с
- возможность точного подбора cv-квалификации и справочной квалификации r/lval из объявленных переменных
- возможность каким-либо образом возвращать типы, чтобы они могли использоваться в объявлениях
- способность передаваться в разных контекстах (легко достижимое, но тем не менее важное условие)
И я был бы счастлив получить ответ. Спасибо!
Комментарии:
1. В некоторых языках OO определение класса само по себе является объектом, который действует как фабрика, производящая экземпляры. C не таков: класс не является объектом, он не является экземпляром какого-либо мета-класса. В лучшем случае вы могли бы зарегистрировать классы в контейнере класса, а статические функции класса и функции-члены взаимодействовали бы с контейнером класса для ваших целей (ведение журнала, общее количество созданных объектов, текущее количество живых объектов, что угодно). Но такие приборы будут навязчивыми.
2. От вызова функции,
integer
иcr_deadbeef
оба имеют значение lvalue. Существуетstd::ref
то, что можно использовать для добавления ссылок.3. Другой МАКРОС, где вы можете использовать
decltype(integer)
(int
) противdecltype(cr_deadbeef)
(intamp;
).4.
getType<anotherClassContainer,0>
это в принципеstd::tuple_element<I, Tuple>
так .
Ответ №1:
Вы не можете различать integer
и cr_deadbeef
на сайте вызовов, поэтому ваш желаемый синтаксис decltype( makeClassContainer(integer, hello, c, c_deadbeef, cr_deadbeef) )
не является стартовым. Вам придется подать decltype
заявление раньше.
Либо напрямую
using my_type_1 = std::tuple<decltype(integer), decltype(hello), decltype(c), decltype(c_deadbeef), decltype(cr_deadbeef)>;
Или через макрос
#include <boost/preprocessor.hpp>
#define ADD_DECLTYPE(a, b, x) decltype(x)
#define MAKE_TYPE_LIST(...) std::tuple< BOOST_PP_TUPLE_ENUM( BOOST_PP_SEQ_TO_TUPLE( BOOST_PP_SEQ_TRANSFORM( ADD_DECLTYPE, 0, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__) ) ) ) >
using my_type_2 = MAKE_TYPE_LIST(integer, hello, c, c_deadbeef, cr_deadbeef);