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

Нетиповой вариативный шаблон класса. Помогите написать.

48 минут назад, AHTOXA сказал:

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

В этом случае - да. И то, не на 100% обязательно. Можно перекодировать команды и данные под имеющуюся шину. constexpr функцией, например, если не вручную.
А если нужно управлять четырьмя выборами устройств, то и совсем не надо. Подать 0x0003 или 0x1080 - одинаково. 

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


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

Не могу скомпилировать первый набросок. Где-то ошибся, но не пойму, где. Правильно ли я пытаюсь передать в шаблон ссылки на структуры constexpr?

Обновил вопрос. Тестовый пример проверяю здесь:

https://www.onlinegdb.com/fork/BJA5GHO3N

Как передать в конструктор шаблона нетиповой параметр - ссылку?

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

#include <iostream>
#include <cstdlib>
#include <cstdint>
#include <cstddef>

struct Test_st { char Let; int Num; };

/*_____________________________________________________________________________*/
constexpr Test_st St1 = { 'A', 10 };
constexpr Test_st St2 = { 'B', 11 };

volatile int Temp1 {1};

template <const Test_st &S00, const Test_st &S01>
class Test_cl
{
	
public:
	Test_cl();
	
};

template <const Test_st &S00, const Test_st &S01>
class Test_cl<S00, S01>::Test_cl()
{
    { Temp1 = S00.Let << 8 | S01.Let; }
}


/*_____________________________________________________________________________*/
int32_t main(void)
{
    std::cout << Temp1 << '\n'; 
	Test_cl <St1, St2> Ti;
    std::cout << Temp1 << '\n';
}

 

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


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

Вот показываю работающий вариант.

#include <iostream>
#include <cstdlib>
#include <cstdint>
#include <cstddef>

struct Test_st { char Let; int Num; };

/*_____________________________________________________________________________*/
constexpr Test_st St1 = { 'A', 10 };
constexpr Test_st St2 = { 'B', 11 };

volatile int Temp1 {1};

template <const Test_st &S00, const Test_st &S01>
class Test_cl
{
	
public:
	Test_cl()
    { Temp1 = S00.Let << 8 | S01.Let; }

};


/*_____________________________________________________________________________*/
int32_t main(void)
{
    std::cout << Temp1 << '\n'; 
	Test_cl <St1, St2> Ti;
    std::cout << Temp1 << '\n';
}

 

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


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

Нашёл ошибку. Слово "class" в определении функции было лишним. Сколько, однако, мелочей нужно контролировать. Продолжу дальше в Кейле для класса порта.

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


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

// это у нас будут типа регистры портов. 
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);
	}

Возвращаюсь к этому коду. 

Поломалось сообщение. В общем, у меня было так, как ниже показал. Создавал объект Port, использовал его функции.

/*  Define GPIO structure pointer  */
	GPIO_TypeDef * GPIO =
		P00.gpio == 'A' ? GPIOA : P00.gpio == 'B' ? GPIOB :
		P00.gpio == 'C' ? GPIOC : P00.gpio == 'D' ? GPIOD :
		P00.gpio == 'E' ? GPIOE : GPIOH;

Если же использовать функции псевдонима, функции должны быть статическими. [ Здесь не соображу, как одна статическая функция работает с разными портами? ]
И указатель на GPIO должен выглядеть static constexpr GPIO_TypeDef * GPIO. Попытался так:
 

static constexpr GPIO_TypeDef * GPIO = reinterpret_cast<const GPIO_TypeDef *>
		(P00.gpio == 'A' ? GPIOA : P00.gpio == 'B' ? GPIOB :
		P00.gpio == 'C' ? GPIOC : P00.gpio == 'D' ? GPIOD :
		P00.gpio == 'E' ? GPIOE : GPIOH);

Получаю:
error: cannot initialize a variable of type 'GPIO_TypeDef *const' with an rvalue of type 'const GPIO_TypeDef *'

Видимо, нужно писать функцию, как в показанном выше фрагменте. Почему и зачем?

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


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

12 часов назад, ViKo сказал:

Здесь не соображу, как одна статическая функция работает с разными портами?

С этим прояснилось. По шаблону ведь создаются разные классы. И в каждом свои статические функции, общие для всех объектов каждого класса. Но самих объектов или совсем нет, или по одному на класс.

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


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

В общем, пока Вандервуда "Шаблоны C++" не прочитаю, толку не будет. Пошёл учиться.

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


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

Вопрос конкретизирую.

	static constexpr volatile GPIO_TypeDef * GPIO { reinterpret_cast<volatile GPIO_TypeDef *>(GPIOA) }; 

	static constexpr volatile GPIO_TypeDef * getGPIO() {
		if (P00.gpio == 'A')
			return reinterpret_cast<volatile GPIO_TypeDef *>(GPIOA);
	}

Почему в шаблоне задать указатель (первое) не получается, а функцию, возвращающую указатель (второе) - получается?

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


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

Здесь разница в том, что для переменной constexpr -- это обязательное требование, а для функции - это лишь пожелание.

То есть, у нас функция getGPIO(), несмотря на то, что перед ней написано constexpr, в действительности не является constexpr.

Я помню, что разбирался с этим, но точных формулировок уже не помню. Вроде бы, reinterpret_cast несовместим с constexpr.

 

 

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


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

 

On 12/19/2019 at 6:19 PM, ViKo said:

Почему в шаблоне задать указатель (первое) не получается, а функцию, возвращающую указатель (второе) - получается?

GPIOA это reinterpret_cast<GPIO_TypeDef *> (GPIOA_BASE), а reinterpret_cast в параметрах шаблона использовать нельзя.

Изменено пользователем artkam

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


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

Спрошу здесь, хоть и не по теме. Читаю книгу Вандервуда про шаблоны. Захотел проверить, как шаблон переменных работает (раздел 5.6 книги).
Не работает в онлайн-отладчиках следующий исходник. Компилятор C++17 задаю, хотя в книге сказано, начиная с C++14. В чем дело?

#include <stdint.h>
#include <iostream>

template<typename Т>
constexpr Т pi {3.1415926535897932385};

int main(void)
{
	using namespace std;

    std::cout << pi<double> << '\n';
    std::cout << pi<float> << '\n';
}

Отбой! Здесь, похоже 'T' была кириллицей написана. Копировал из книги, а там много символов неправильно определяется.

Однако, подложена свинка.

По мотивам. А нет ли такого шрифта, чтобы символы кириллицы и английские различались в Notepad++? Или плагина к нему. Чистое любопытство.

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


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

25 минут назад, ViKo сказал:

По мотивам. А нет ли такого шрифта, чтобы символы кириллицы и английские различались в Notepad++? Или плагина к нему. Чистое любопытство.

Элементарно: Любой редактор понимающий разные кодировки, переключаете в другую кодировку (в неправильную) и русские буквы становятся кракозябрами. Например вместо Win1251 включить DOS или KOI.

Ну это конечно только для однобайтовых символов, с Unicode-ом не получится так.

Я все тексты набираю/редактирую в DosNavigator-е, так там это делается нажатием одной кнопки F8.  :good:

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


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

42 минуты назад, jcxz сказал:

Ну это конечно только для однобайтовых символов, с Unicode-ом не получится так.

Я в UTF-8 пишу. Переключил на ANSI, вместо Т получил Рў. Годится! 

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


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

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

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

Гость
Ответить в этой теме...

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

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

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

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

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

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