Читаемый синтаксис для назначения назначения адресов.

avraliov.andrey
avraliov.andrey

В ada:

var: mod2*32;

for var'address use to_adress (16#405338#)

Хотелось бы в С++ что то в этом роде:

std::uint32_t var;

for var using address(405338);

Да, понимаю что нужно добавить новое ключевое слово в язык. Может кто предложит идею в более простой реализации. Только, думаю не стоит говорить что reinterpret_cast<>()... это вполне замечательный вариант. Да он работает, но читаемость кода заметно ухудшается со всеми вытекающими.

-3
рейтинг
9 комментариев
yndx-antoshkka
А такой вариант вас устроит:

template <uinptr_t A, class T>
struct dma: std::reference_wrapper<T> {
dma() noexcept
: std::reference_wrapper<T>{ *reinterpret_cast<T*>(A) }
{}

template <class U>
explicit dma(U&& u) noexcept(is_nothrow_assignable_v<T, U>)
: std::reference_wrapper<T>{ *reinterpret_cast<T*>(A) }
{
*this = std::forward<U>(u);
}
};

// Usage:
dma<405338, std::uint32_t> var;
dma<40583, std::uint32_t> var = 100;

Бонусом можно будет навешать static_assert на alignment и платформо специфичные допустимые диапазоны адресов.
yndx-antoshkka
avraliov.andrey
yndx-antoshkka, Спасибо за ответ. Да это вариант, сам пользую подобные вещи. Это можно запихать в либу. Но! количество кода с читаемостью и последующим сопровождением на лицо. Страуструп на Cppcon2016 сам сказал что нужен компромисс между фичами в языки и библиотеках. Одни дают экспрессивность языка, другие время компиляции. Мне кажется что мой любимый С++ (как один из основных языков в этом программирования железа) ДОЛЖЕН делать это просто и дубово, с проверкой типа, что это не просто int, а адрес на уровне языка. Развитие темы мне кажется это так же как ada - простой синтаксис для битовых полей указанной переменной (насколько я зная битоые поля в c++ оставлены на откуп разработчика компилятора.).
в ada:
for var at 0 range 0 .. 3;
что означает в переменной var в нулевом байте использовать только первые четыре бита.
Все с гарантией от стандарта на уровне языка.

Как это будет выглядеть на С++ мы с вами представляем!!! Разница есть
avraliov.andrey
yndx-antoshkka
avraliov.andrey, предлагаю продумать следующую идею:

"Набор функций и классов, полезных для embedded разработки."

Давайте соберём побольше полезных классов/конструкций языка и напишем proposal сразу на добавление их всех. Если есть уже готовая популярная библиотека - дайте на неё ссылку, задача упростится :)
yndx-antoshkka
avraliov.andrey
yndx-antoshkka, Библиотек таких не видел. Много embedded кода вежде на обычном С. Энтузиасты С++ выкручиваются сами способами типа вашего. Лично я пока не вижу способа решить проблему без дополнения именно синтаксиса языка, но я программист любитель (по профессии я врач), до уровня Антона Полухина мне не угнаться. Но если вы с высоты своего опыта видите что это реально сделать имеющимися средствами хотя бы С++17, то скажите. Я буду думать, искать и пробовать. И на какой площадке обсуждать, куда присылать?
avraliov.andrey
yndx-antoshkka
avraliov.andrey, обсуждать стоит здесь, присылать сюда же :)

У меня нет особого опыта в embedded разработке, я не знаю типичных задач и проблем embedded разработчика. Так что нужен человек, который будет активно жаловаться на что, чего ему не хватает в C++
yndx-antoshkka
avraliov.andrey
yndx-antoshkka, Ну мне после приобретенного опыта в ada программировании стало очевидно, что в С++ нужен способ удобного и гарантированного назначения адреса переменным, удобная и гарантированная работа с битовыми полями.
что бы можно было написать:

typename enable_t;
for enable using size 1; //(bit)

typename reset_t;
for reset using size 1; //(bits)

typename data_t;
for data using size 8; //(bits)

struct status_register
{
enable_t en;
reset_t res;
data_t data;
};
for status_register using size 16;
for status_register using address 34657678;
for status_register.en using range 0..1;
for status_register.reset using range 1..2;
for status_register.data using range 8..15;

На выходе получаем регистр с адресом и использьванием только нужных битов:
1100000011111111 по адресу ххх.

Читаемость и программируемость как мне кажется на высоте.

Если битовые операции делать через |= &= ~=, то мне кажется это уже не с++ а галимый С, от которого мы вроде пытаемся уйти в сторону типобезопастности , читаемости, выразительности...
avraliov.andrey
yndx-antoshkka
avraliov.andrey, Да, c полями битов в стандарте так себе:

[class.bit] Allocation of bit-fields within a class object is implementation-defined. Alignment of bit-fields is implementation-defined.

Надо подумать, как это исправить, ничего не разломав. По идее нужен специальный синтаксис, который говорит что биты идут строго в том порядке, что написали
yndx-antoshkka
avraliov.andrey
yndx-antoshkka, абсолютно с вами согласен!!!
avraliov.andrey
avraliov.andrey
yndx-antoshkka, нашел в инете интересное решение. Не то что хотелось бы в идеале но тем не менее.

#include <type_traits>
#include <cstddef>
#include <cstdint>

template <std::size_t LastBit>
struct MinimumTypeHelper {
typedef
typename std::conditional<LastBit == 0 , void,
typename std::conditional<LastBit <= 8 , std::uint8_t,
typename std::conditional<LastBit <= 16, std::uint16_t,
typename std::conditional<LastBit <= 32, std::uint32_t,
typename std::conditional<LastBit <= 64, std::uint64_t,
void>::type>::type>::type>::type>::type type;
};

template <size_t Index, size_t Bits = 1>
class BitField {
private:
enum {
Mask = (1u << Bits) - 1u
};

typedef typename MinimumTypeHelper<Index + Bits>::type T;
public:
template <class T2>
BitField &operator=(T2 value) {
value_ = (value_ & ~(Mask << Index)) | ((value & Mask) << Index);
return *this;
}

operator T() const { return (value_ >> Index) & Mask; }
explicit operator bool() const { return value_ & (Mask << Index); }
BitField &operator++() { return *this = *this + 1; }
T operator++(int) { T r = *this; ++*this; return r; }
BitField &operator--() { return *this = *this - 1; }
T operator--(int) { T r = *this; --*this; return r; }

private:
T value_;
};

template <size_t Index>
class BitField<Index, 1> {
private:
enum {
Bits = 1,
Mask = 0x01
};

typedef typename MinimumTypeHelper<Index + Bits>::type T;
public:
BitField &operator=(bool value) {
value_ = (value_ & ~(Mask << Index)) | (value << Index);
return *this;
}

explicit operator bool() const { return value_ & (Mask << Index); }

private:
T value_;
};

union reg
{
std::uint32_t raw;
BitField<0,1> en;
BitField<1,1> rst;
BitField<5,3> data;
};

int main()
{
reg my_reg;

my_reg.data = 4;

return 0;
}
avraliov.andrey
Другие идеи
Группа создана, чтобы собирать предложения к стандарту C++, организовывать их внутренние обсуждения, помогать готовить их для отправки в комитет и защищать на общих собраниях в рабочей группе по С++ Международной организации по стандартизации (ISO).