Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 02.11.2022, 23:57   #1
Loksiin12
Форумчанин
 
Регистрация: 04.10.2020
Сообщений: 136
По умолчанию Не могу получить доступ к полям структуры, структура является элементом рекурсивного списка

Есть такой код.
Код:
struct NullType {};
template <typename Head, typename Tail = NullType>
struct Typelist{};
 
template <int C, template <int> class T, int Z = 1>
class MakeList
{
    typedef typename MakeList<C-1, T, Z + 1>::Result Tail;
 
public:
    typedef Typelist<T<Z>, Tail> Result;
};
template <template <int> class T, int Z>
class MakeList<0, T, Z>
{
public:
    typedef NullType Result;
};
 
template <class TList> struct Length;
template <>
struct Length< NullType >
{
    enum { value = 0 };
};
template <class T, class U>
struct Length< Typelist<T, U> >
{
    enum { value = 1 + Length<U>::value };
};
template <class TList, unsigned int Index>struct TypeAt;
template <class Head, class Tail>
struct TypeAt<Typelist<Head,Tail>,0>
{
    typedef Head Result;
};
template <class Head, class Tail, unsigned int Index>
struct TypeAt<Typelist<Head, Tail>,Index>
{
    typedef typename TypeAt<Tail,Index-1>::Result Result;
};
 
template <typename T, unsigned int Z>
class TupleElement
{
public:
    T & get() 
    {
        return m_value;
    }
private:
    T m_value;
};
 
 
template <typename List, unsigned int Z = 0>
class TupleImpl;
    
template <typename T,typename U,unsigned int Z>
class TupleImpl<Typelist<T, U>, Z>
    : public TupleElement<T, Z - 1>
    , public TupleImpl<U, Z - 1>{ };
 
template <>
class TupleImpl<NullType, 0>
{ };
 
template <int a>
struct __char{char arr_[a];};
 
template <int T = sizeof(int)>
class Tuple : public TupleImpl<typename MakeList<T, __char>::Result, T>
{ 
    typedef typename MakeList<T, __char>::Result ElementsList;
        
public:
    template <unsigned int Index>
    typename TypeAt<ElementsList, Index>::Result & get() 
    {
        TupleElement<typename TypeAt<ElementsList, Index>::Result, Index> & el = *this;
        return el.get();
    }
    enum 
    {
        Size = Length<ElementsList>::value
    };
    
};
 
template<typename Tuple, unsigned int Z = Tuple::Size>
struct TupleFor__
{
    template<typename F>
    static void run(Tuple&tpl, F f, unsigned int i)
    {
        if 
            (i == Z - 1) f(tpl.template get<(Z - 1)>());
        else
            TupleFor__<Tuple, (Z - 1)>::run(tpl, f, i);
    }
};
 
template <typename Tuple>
struct TupleFor__<Tuple, 0>
{
    template <typename F>
    static void run(Tuple&tpl, F f, unsigned int i) { }
};
 
template <typename Tuple, typename F>
void TupleFor_(Tuple& t, F f, unsigned int i) 
{
    TupleFor__<Tuple>::run(t, f, i);
}
 
template<typename Tuple, typename F>
void TupleFor(unsigned int first, unsigned int last, Tuple t, F f)
{
    for (unsigned int i = first; i <= last; ++i)
        TupleFor_(t, f, i);
}
 
struct CoutPrinter {
    template <typename T>
    void operator()(T const & v) const 
    {
        cout<<v<<' '<<endl;
    }
};
 
int _tmain(int argc, _TCHAR* argv[]){setlocale(LC_ALL,"rus");
Tuple<>tpl;
 
//tpl.get<0>().arr_[0]='O';
cout<<" symbol tpl.get<0> "<<&(tpl.get<0>().arr_)<<endl;
 
cout << sizeof(tpl.get<0>())<< sizeof(tpl.get<1>()) << '\n'
              << sizeof(tpl.get<2>()) << '\n'
              << sizeof(tpl.get<3>())<<" sizeof(tpl) "<<sizeof(tpl)<<endl;
              ;
//TupleFor(0, 3, tpl, CoutPrinter());
//TupleFor_(tpl,CoutPrinter(),2);
 
_getch();
return 0;
}
Создаётся не совсем стандартный объект tpl, который содержит 4ре структуры на 1 2 3 4 байта. Всего получается 10ть байт. Если я пытаюсь получить адрес любой структуры по нужному уровню например &(tpl.get<0>().arr_) или &tpl.get<0>() или получить доступ к полям элементам этих структур, или записать туда значение tpl.get<0>().arr_[0]='O'; получаю ошибку.
Код:
>c:\users\user\documents\visual studio 2012\projects\minmax\minmax\minmax.cpp(117): error C2440: инициализация: невозможно преобразовать "Tuple<>" в "TupleElement<T,Z> &"
1>          with
1>          [
1>              T=__char<1>,
1>              Z=0
1>          ]
1>          c:\users\user\documents\visual studio 2012\projects\minmax\minmax\minmax.cpp(189): см. ссылку на создание экземпляров функции шаблон при компиляции "__char<a> &Tuple<>::get<0>(void)"
1>          with
1>          [
1>              a=1
1>          ]
1>          c:\users\user\documents\visual studio 2012\projects\minmax\minmax\minmax.cpp(191): см. ссылку на создание экземпляров функции шаблон при компиляции "__char<a> &Tuple<>::get<0>(void)"
1>          with
1>          [
1>              a=1
1>          ]
========== Построение: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========
Прошу помочь разобраться с этой ошибкой подскажите чего не хватае этой схеме, чтобы она могла работать нормально. Основная идея это использование элементов списка которые есть в объекте tpl.
Loksiin12 вне форума Ответить с цитированием
Старый 03.11.2022, 07:48   #2
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Цитата:
Сообщение от Loksiin12 Посмотреть сообщение
невозможно преобразовать "Tuple<>" в "TupleElement<T,Z> &"
ну, так ежели *this имеет тип Tuple<>, то ссылка на него должна быть Tuple<>&:

Код:
        //TupleElement<typename TypeAt<ElementsList, Index>::Result, Index> & el = *this;
        auto& el = *this;
дальше разбираться не стал, там идёт бесконечный рекурсивный вызов get(), только типы не совпадут, так что до самой рекурсии дело не доходит.

идёт изобретение std::tuple ?
Алексей1153 вне форума Ответить с цитированием
Старый 03.11.2022, 20:28   #3
Loksiin12
Форумчанин
 
Регистрация: 04.10.2020
Сообщений: 136
По умолчанию

А с этой строкой что
Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
TupleElement<typename TypeAt<ElementsList, Index>::Result, Index> & el = *this;
,
она не нужна, с обычными типами работает нормально, но мне нужно сгенерировать именно поля а не обычные типы?
Loksiin12 вне форума Ответить с цитированием
Старый 06.11.2022, 07:05   #4
Loksiin12
Форумчанин
 
Регистрация: 04.10.2020
Сообщений: 136
По умолчанию

На одном из форумов подсказали такое решение
Код:
    typename TypeAt<ElementsList, Index>::Result & get() 
    {
        typename TupleElement<TypeAt<ElementsList, Index>::Result, Index>* el 
            = reinterpret_cast< TupleElement<TypeAt<ElementsList, Index>::Result, Index>* >(this);
        return el->get();
    }
Здесь возникают неоднородные классы и его приходится приводить таким способом. Но можно записать более короче о чём пользователь выше пытался сказать а я не понял. Вот так.
Код:
auto* el 
            = reinterpret_cast< TupleElement<TypeAt<ElementsList, Index>::Result, Index>* >(this);
Loksiin12 вне форума Ответить с цитированием
Старый 06.11.2022, 08:56   #5
Алексей1153
фрилансер
Форумчанин
 
Регистрация: 11.10.2019
Сообщений: 960
По умолчанию

Цитата:
Сообщение от Loksiin12 Посмотреть сообщение
reinterpret_cast
это почти всегда признак того, что что-то делается неправильно

и логически я не понимаю, как и зачем тип Tuple<> топором вбивать в тип TupleElement<TypeAt<ElementsList, Index>::Result, Index>

по-моему, это чистое UB
Алексей1153 вне форума Ответить с цитированием
Старый 06.11.2022, 09:01   #6
Loksiin12
Форумчанин
 
Регистрация: 04.10.2020
Сообщений: 136
По умолчанию

Цитата:
Сообщение от Алексей1153 Посмотреть сообщение
по-моему, это чистое UB
ну работает. UB на шаблонных рекурсиях идёт сразу проверял. Даже программа не скомпилируется. По идее так объявлен тип el. Достаточно сложный объект.

Последний раз редактировалось Loksiin12; 06.11.2022 в 09:04.
Loksiin12 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не могу получить доступ к файлу через PascalABCNET Neitrat Помощь студентам 22 07.02.2016 16:26
Не могу получить доступ к файлу через PascalABCNET Neitrat Паскаль, Turbo Pascal, PascalABC.NET 0 06.02.2016 17:27
Не получается пройтись по коллекции через foreach и получить доступ к полям Николавна C# (си шарп) 5 04.05.2014 16:44
Доступ к полям класса Pykhov Общие вопросы Delphi 1 20.04.2014 16:41
Не могу получить доступ к файлам Orsini Общие вопросы C/C++ 0 13.06.2012 12:09