Перейти к содержанию
    

Плавный переход C -> C++ под МК

Говорят, даже на Питоне микроконтроллеры прогают. Я, правда, сам не пробовал.

55 минут назад, Arlleex сказал:

А вот так уже работает

Да, конкретные специализации шаблонов метода (или всего класса) уже можно перенести в .cpp. То есть, косяк в том, что имя типа шаблона не видно в файле .cpp. Хотя, если шаблонный метод вынести из класса, оставив в том же файле .hpp, то всё компилируется. Такой вот попандос.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 minutes ago, EdgeAligned said:

а Питоне микроконтроллеры прогают

Конечно. Причем без всего этого геморроя с шаблонами.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, Arlleex сказал:

Есть ли какой-то чисто практический пример, а не академический, когда указатели на методы или данные класса действительно лаконично решают задачу?

Странный вопрос... Например - если имеется много переменных-членов, которые сами по себе независимы (логически), но в какой-то момент их нужно обработать однотипно, все сразу. Как быть в этом случае? Самое логичное и оптимальное: создать массив указателей на члены класса и с помощью него обработать.
Например: В классе есть много разных указателей на объекты, созданные в динамической памяти (простые, без деструкторов). В деструкторе класса их нужно удалить. Вот с помощью массива указателей на члены класса это сделать удобно и оптимально.

Другой вариант: На вход некоторой член-функции класса нужно подать const-массив, описывающий способ обработки чего-то. В этом массиве нужно сослаться на какие-то член-данные или методы класса. Здесь тоже нужны указатели на члены класса.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

34 minutes ago, jcxz said:

 с помощью массива указателей на члены класса ....

 самый "практический способ" выстрелить себе в ногу

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Возможно для однотипного изменения какого-то элемента в целом списке объектов, но когда заранее точно не известно, какой мембер надо менять. Чтобы кучу if() не писать, а возложить все на компилятор.

В голову пример такой пришел. Есть панель с подсветкой, подсветка из отдельных управляемых RGB-светодиодов. Каждый диод описывается как

class Led {
  public:
    u8 red, green, blue;
  ...
};


И теперь в интерфейсе настройки подсветки есть ползунки изменения баланса синего, красного и зеленого (отдельно). Тянем красный - должны изменяться значения красного во всех диодах, и так для любых компонентов

void changeBalance(Led leds[], u8 Led::*color, u8 value) {
  for (auto i = 0; i < MAX_LEDS_QNT; ++i)
    leds[i].*color = value;
}


Ну а в точке принятия решения, какой цвет будем менять

u8 Led::*color;

if (...)
  color = &Led::red;
else if (...)
  color = &Led::green;
else color = &Led::blue;

u8 value = ...; // get_new_value()

changeBalance(LedArray, color, value);


В принципе, необходимость таких указателей понятна.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 23.06.2024 в 20:31, Arlleex сказал:

Я хотел, чтобы в заголовочнике был только "интерфейс" для быстрого охвата глазами. А в реализации уже потроха - туда смотреть не надо.

I. Стандартный подход

отделить мух от котлет через имплементарный заголовок с реализацией

в файле myTemplate.h

template <typename T>
void f(T value);

#include "myTemplateImpl.h" // Включаем реализацию здесь 

Файл myTemplateImpl.h

template <typename T>
void f(T value)
{
// Реализация функции
} 

В этом случае мы отделяем объявление и определение шаблонной функции в разные файлы, но включаем файл с реализацией myTemplateImpl в конце файла с объявлением myTemplate.h.

 

II. альтернативный подход

Сделать инстанцировку в исходном файле.

Файл myTemplate.h

template <typename T>
void f(T value); 

Файл myTemplate.cpp

#include "myTemplate.h"

template <typename T>
void f(T value)
{
// Реализация функции
}

// Явная инстанцировка для нужных типов
template void f<int>(int);
template void f<double>(double);

Использование

#include "myTemplate.h"
  
int main() 
{
    float a = 1.0f;
    double b = 3.14;
    f<float>(a); //для варианта II ошибка, т.к. нЭт его (нет инстанцировки для float в cpp)
    f<double>(b); //будет работать для обоих вариантов
    return 0;
}

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

  

42 minutes ago, Arlleex said:

В голову пример такой пришел.

 

Если кроме хранения цвета класс Led больше ничего не делает, то достаточно его сделать просто структурой, а еще лучше union, чтобы была возможность менять как отдельно поля цветов, так и сразу все три цвета.

Тогда не нужны такие крайне небезопасные способы обращения к полям и тем более их изменениям извне.

Такие костыли с указателями на поля класса лишь демонстрируют что здесь в коде что-то не так, первый звоночек так сказать ))

 

Или все же предполагается в будущем Led будет что-то еще и делать (хотя бы типа set/get)?

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

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, juvf сказал:

I. Стандартный подход

Этот да, мне известен))

Цитата

II. альтернативный подход

Сделать инстанцировку в исходном файле.

А этот я выше в своем же сообщении тоже выложил.

Только маленький вопрос по синтаксису. Я писал

template<> func<int>(int a) {
}

а Вы

template func<int>(int a);

т.е. без <> после ключевого слова template.

Имеет ли это какое-то значение? Или это на уровне синтаксиса абсолютно ничего не значит?

P.S. Не ну C++:sad::suicide2:Вот так работает

template<> func<int>(int a) {
}

вот так нет

template func<int>(int a) {
}

вот так работает

template func<int>(int a);

вот так нет

template<> func<int>(int a);

 

1 час назад, Forger сказал:

Такие костыли с указателями на поля класса лишь демонстрируют что здесь в коде что-то не так, первый звоночек так сказать ))

Это всего лишь пример, придуманный для мысленного представления как это можно было бы использовать на практике)) Не относитесь строго)

Цитата

Или все же предполагается в будущем Led будет что-то еще и делать (хотя бы типа set/get)?

Как минимум, развивая идею с указателями на мемберы, нужно было упрятать цвета в private, а доступ к ним осуществлять через публичные сеттеры, и вот уже указателями на сеттеры можно было оперировать. Не стал писать так, чтобы упростить портянки примеров.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 24.06.2024 в 13:15, Arlleex сказал:

Имеет ли это какое-то значение? Или это на уровне синтаксиса абсолютно ничего не значит?

имеет. тут стрельнуть себе в ногу можно... 

template<> func<int>(int a) { } //это явная специализация
template func<int>(int a); // это явная инстанцировка

в чем различие!? Когда нужно сделать отдельную реализацию для белой вороны какого-то типа, то делается явная специализация. поясню на примере

Файл myTemplate.cpp

#include "myTemplate.h"

template <typename T> void f(T value)
{
// Общая реализация для всех типов
}

// Реализация явной специализации для типа `unsigned int`
template <>
void f<unsigned int>(unsigned int value) 
{
    printf("Hello unsigned int = %u");
}


// Явная инстанцировка для нужных типов
template void f<int>(int);
template void f<double>(double);

Использование

 

#include "myTemplate.h"
  
int main()
{
int a = -1;
double b = 3.14;
unsigned int c = 123;

f<int>(a); // Использует общую реализацию

f<double>(b); //Использует общую реализацию
  
f<unsigned int>(c); //Использует специализированную реализацию, которая выводит "Hello unsigned int = *"
  
return 0;
}

вобщем как-то так... 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, juvf сказал:

template<> func<int>(int a) { } //это явная специализация
template func<int>(int a); // это явная инстанцировка

Не понятно тут только вот это. Это уже именно создание реального прототипа функции?

Т.е. мы говорим компилятору - у нас где-то есть template. А ну-ка создай прототип шаблонной функции с таким-то типом. Так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 24.06.2024 в 13:54, Arlleex сказал:

Т.е. мы говорим компилятору - у нас где-то есть template. А ну-ка создай прототип шаблонной функции с таким-то типом. Так?

да. компилятор создаст вам функцию 

void f(int value)
{
// Общая реализация 
}
В 02.06.2024 в 19:24, Arlleex сказал:

В общем купил себе книжечку, толстееееннную))

 

а в этой книжке это не изложено? Или там нужно выкуривать эту инфу? 

ps так то конечно, лучше сразу получить знания на практике: есть практическая цель - есть вопрос: "а как это решить и в чем различие?". Чем курить книжку долгое время без практики. Все равно половину забудешь.  Просто интересно, там это есть или нет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В 23.06.2024 в 20:31, Arlleex сказал:

Я хотел, чтобы в заголовочнике был только "интерфейс" для быстрого охвата глазами. А в реализации уже потроха - туда смотреть не надо.

это не единственная причина убрать шаблон в cpp и сделать явную инстанцировку. Если реализовать шаблон полностью в *.h. (или в *.h и в *_impl.h), допустим потом если вызвать эту функцию f<int> 10 раз в одном файле, то компилятор встретив первый раз f<int>, сгенерирует код и после ужё встретив в этом файле f<int> компиялтор будет использовать уже сгенерированные код. 

Но если вы ещё в десяти файлах исходников вызовите f<int>, то компилятор будет гернерить код f<int> для каждого вашего *.cpp, где вы его вызовите.  Один раз на каждый *.cpp где хоть раз есть вызов  f<int>. Т.е. ваш main.o будет содержать отдельную f<int>, ваш noMain.o будет содержать отдельную f<int>, и все остальные объектники будет каждый содержать свой f<int>. Потом, при  линковке, линкер выкинет все дубликаты и будет всего одна f<int> для всех. 

 

Если вы вынесете определение шаблона f<int> в *.cpp и сделаете явную  инстанцировку, то при компиляции myTemplate.cpp и встетив строчку template void f<int>(int); у вас компиялтор сгенерирует f<int> в отдельный myTemplate.o . При компиляции остальных файлов *.срр генерации f<int> не будет. Получите  myTemplate.0 с кодом  f<int>. Линковщик потом свяжет  весь проект. 

Итоговый код будет одинаковый в обоих случаях, но время компиляции уменьшится. У каждого метода есть ++ и --.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

45 минут назад, juvf сказал:

а в этой книжке это не изложено? Или там нужно выкуривать эту инфу? 

Я ее пока что довольно выборочно читаю, поэтому возможно что пропустил.

Хотя в предисловии там предупреждали, что книжечка расчитана на опытных в плюсах юзеров.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Кстати, насчет задания/изменения цвета. В этом плане удобно бывает оперировать не RGB, а HSV (HSB) моделью. То есть, оттенок-насыщенность-яркость. Цвет задается компонентой H в диапазоне 0 - 359, а яркость - компонентой V (L) в диапазоне 0 - 100. При значении компоненты S = 100 получаются чистые цвета. Если S = 0 получается белый цвет. Я использовал модель HSB для работы с эффектами на пиксельных светодиодах. То есть, все цветовые эффекты описывал в HSB, а перед загрузкой в линейки преобразовывал  HSB -> RGB. 

3 часа назад, Arlleex сказал:

Не ну C++:sad::suicide2:Вот так 

А я об этом раньше ведь говорил, но меня не понимали, говорили, что ++ это супер-круть типа и ваще. 🙂 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, EdgeAligned сказал:

говорили, что ++ это супер-круть типа и ваще.

так и есть круть. 

2 часа назад, Arlleex сказал:

Я ее пока что довольно выборочно читаю,

если что не понятно, спрашивайте. Столько интересного.... 😉 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...