haker_fox 61 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 19 minutes ago, dxp said: Этот термин идёт из языков, Кажется, я узнал кучу новых терминов: "объект первого класса", "функтор". Вернее я их слышал, но не предавал им значения... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 3 hours ago, haker_fox said: Кажется, я узнал кучу новых терминов: "объект первого класса", "функтор". Вернее я их слышал, но не предавал им значения... И забудьте сразу это словоблудие. Если конечно не хотите потролить кого-нибудь. Понятие функтор вы не найдете в справочнике по C++, как и понятие "объекты первого класса" тоже метафора рожденная не от C++. Так что я б посылал лесом такую терминологию, она засоряет понимание плюсов. Лябды - это функции-объекты, но не любые какие вздумается. И они обязательно должны иметь функцию. Поэтому и зовут их лямбда-выражения. Это феномен в себе не подлежащий редуцированию или выводу из других сущностей. Я сам привел понятие "функтор" только чтоб развеселить тему. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 4 часа назад, dxp сказал: Лямбда-функция в С++ - это анонимный функтор. Согласитесь, что функтор и функция - это разные вещи. Первый - это объект (первого класса в том числе), вторая просто код. Соглашусь, что разные. Функтор - это класс с перегруженным operator(), предназначенный для манипулирования объектами контейнера. Не соглашусь, что лямбда-функция - это функтор. Лямбда-выражения в C++ используются именно в виде анонимных функций, без имени, адреса, используемых в месте определения. Насчет порядка функций - это, видимо, из питона и т.п. термин. В учебниках по C/C++/C# не встречал. Да и какой может быть порядок, если вложенные функции невозможны. Кроме этих лямбд. Нисколько не сомневаюсь, что вы продвинутый программист и в теории и на практике. Однако, лямбда-функция означает лямбда в форме функции. Или наоборот. И уж точно не было корректным ваше безоговорочное "не функции вообще". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 22 minutes ago, ViKo said: Соглашусь, что разные. Функтор - это класс с перегруженным operator(), предназначенный для манипулирования объектами контейнера. Не соглашусь, что лямбда-функция - это функтор. Лямбда-выражения в C++ используются именно в виде анонимных функций, без имени, адреса, используемых в месте определения. Насчет порядка функций - это, видимо, из питона и т.п. термин. В учебниках по C/C++/C# не встречал. Да и какой может быть порядок, если вложенные функции невозможны. Кроме этих лямбд. Нисколько не сомневаюсь, что вы продвинутый программист и в теории и на практике. Однако, лямбда-функция означает лямбда в форме функции. Или наоборот. И уж точно не было корректным ваше безоговорочное "не функции вообще". Все равно не понял, чего вы хотите. Так что - ли ? template<typename T, typename... Args> class Pack { public: static T comb(T v) { return v << 8; } static T comb(T first, Args... args) { return (first << 8) | comb(args...); } }; int main(void) { long sum = Pack<char, char>::comb(1,2); return 0; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба Так, да не так, DASM. Я хочу в шаблон класса передать не типы, а значения. Типы я и так знаю. Они не меняются. И вот прибыл в лингвистический тупик. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 52 minutes ago, ViKo said: Так, да не так, DASM. Я хочу в шаблон класса передать не типы, а значения. Типы я и так знаю. Они не меняются. И вот прибыл в лингвистический тупик. Ну тогда до с++17 похоже что ничего не выйдет ! When instantiating a class template, we have to pass in the types explictly (at least until C++17): But when instantiating a function template, the compiler can often figure the types out: Не надо в класс короче пихать. https://foonathan.net/2016/11/template-argument-deduction/ Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба Не-ти-по-вой параметр! http://ci-plus-plus-snachala.ru/?p=3989 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 16 minutes ago, ViKo said: Не-ти-по-вой параметр! http://ci-plus-plus-snachala.ru/?p=3989 так у него тип явно указан - template <typename T, int MAXSIZE> А вы, похоже, хотите выводить их значений, что работает для функций, но не работает для классов Вот template<auto n> struct B { /* ... */ }; B<5> b1; VS 2017 это не переварил в С++ 17 , но скушал в "ISO C++ Latest Draft Standard (/std:c++latest)" Писать на новейших драфтах для mcu это конечно шикарно.. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 3 минуты назад, DASM сказал: так у него тип явно указан - template <typename T, int MAXSIZE> И я укажу. Я свои типы знаю. Не могу передать эти параметры в шаблонные функции. Об этом и спрашивал в стартовом сообщении. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DASM 0 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 15 минут назад, ViKo сказал: И я укажу. Я свои типы знаю. Не могу передать эти параметры в шаблонные функции. Об этом и спрашивал в стартовом сообщении. в стартовом было вообще нечто несвязное. Далее прояснили "Не получается задать в шаблоне значения и по ним функции определять внутри класса." Теперь стало вообще ничего непонятно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба Ну вот, набросал кусочек. #include <iostream> #include <cstdlib> #include <cstdint> #include <cstddef> // тестовая структура для проверки работы класса порта struct PortStruct { volatile uint32_t pinValues; // значения ног volatile uint32_t pinDirs; // направления ног (0 = вход) }; // это у нас будут типа регистры портов. static PortStruct portA { 0, 0 }; static PortStruct portB { 0, 0 }; // шаблонный класс порта. Параметр шаблона - буква порта (для проверки идеи этого достаточно) template <char portLetter = 'A'> class Port { public: // выдать указатель на регистры порта. static constexpr volatile PortStruct* getPortStruct() { if (portLetter == 'A') return reinterpret_cast<volatile PortStruct*>(&portA); return reinterpret_cast<volatile PortStruct*>(&portB); } // чтение/запись порта целиком static void set(uint32_t value) { getPortStruct()->pinValues = value; } static uint32_t get() { return getPortStruct()->pinValues; } // чтение одной ножки порта static void setPin(int pinNum, bool on) { if (on) getPortStruct()->pinValues |= (1UL << pinNum); else getPortStruct()->pinValues &= ~(1UL << pinNum); } // вложенный класс "шина" template<unsigned... Pins> struct Bus { // выдать маску шины (единички в тех позициях, которые включены в эту шину) static constexpr uint32_t getMask() { return getMask<Pins...>(); } // прочитать значение шины (только те биты, которые включены в шину) static uint32_t get() { auto result { 0u }; for (auto pin = 0u, mask = getMask(), value = Port::get() & mask; value; mask >>= 1, value >>= 1) { if (mask & 1u) { if (value & 1u) result |= (1u << pin); ++pin; } } return result; } // запись значения в шину static void set(unsigned value) { for (auto mask = getMask(), pin = 0u; mask; mask >>= 1, ++pin) { if (mask & 1u) { Port::setPin(pin, value & 1); value >>= 1; } } } private: // вспомогательная шаблонная функция для вычисления маски шины template<uint32_t FirstPin, uint32_t... OtherPins> static constexpr uint32_t getMask() { uint32_t value { 0 }; if constexpr (sizeof...(OtherPins) > 0) { value = getMask<OtherPins...>(); } value |= (1 << FirstPin); return value; } }; }; int main() { using PortA = Port<'A'>; PortA::setPin(1, true); // установим бит 1 в единичку std::cout << "Читаем порт, должно быть число 2: " << PortA::get() << std::endl; PortA::setPin(2, true); // установим бит 2 в единичку std::cout << "Читаем порт, должно быть число 6: " << PortA::get() << std::endl; PortA::set(0); std::cout << "Читаем порт, должно быть число 0: " << PortA::get() << std::endl; // шина из битов 0, 2, 4 порта A using PortA_Pins024 = PortA::Bus<0, 2, 4>; static_assert (PortA_Pins024::getMask() == 21, ""); // проверим маску. std::cout << "Читаем шину, должно быть число 0: " << PortA_Pins024::get() << std::endl; PortA_Pins024::set(1); std::cout << "Читаем шину, должно быть число 1: " << PortA_Pins024::get() << std::endl; std::cout << "Читаем порт, должно быть число 1: " << PortA::get() << std::endl; PortA_Pins024::set(2); std::cout << "Читаем шину, должно быть число 2: " << PortA_Pins024::get() << std::endl; std::cout << "Читаем порт, должно быть число 4: " << PortA::get() << std::endl; PortA_Pins024::set(3); std::cout << "Читаем шину, должно быть число 3: " << PortA_Pins024::get() << std::endl; std::cout << "Читаем порт, должно быть число 5: " << PortA::get() << std::endl; } Можно потыкать вот тут. Думаю, идея понятна. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба Спасибо, Антон! Запись одной ножки пропустили. Вернее, запись есть, а в комментарии написано "чтение", а чтения нет. И я не вижу, как getMask для одного параметра работает. А, это в конце, нашёл. Ага, sizeof... использовали. Вот оно, решение вопроса по теме. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба Да, запись ножки есть, комментарий не соответствует. Чтение по аналогии, там тривиально. getMask в случае одного параметра обрабатывается в ветке if constexpr()... Вернее, когда параметр один, то эта ветка не выполняется. Это вариант для c++17. Если c++11, то придётся делать две функции - с одним параметром и с несколькими. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AlexandrY 3 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба 28 minutes ago, ViKo said: Вот оно, решение вопроса по теме. Какое же это решение. Простейший цикл for завернули в многоэтажный нечитабельный шаблон. При этом наблюдается отсутствие детерминизма. Про потокозащищенность даже молчу. При реальном количестве портов их свойств этот шаблов превратится в монстра. А ведь можно было обойтись простым и ясным массивом. Что ни говорите, но плюсам не тягаться с простыми операторами C в этом деле. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ViKo 1 12 декабря, 2019 Опубликовано 12 декабря, 2019 · Жалоба Это именно то, что я спрашивал. Будем смотреть, во что компилируется, а не сколько в нём этажей. Есть мысли сделать класс полного порта и наследственный класс на произвольное количество выводов. В результате должно компилироваться в команды, обращающиеся непосредственно к регистрам GPIO. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться