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

Есть следующая структура классов:

RCC.h

#pragma once

template<auto address>
class Register
{
public:

    static void Set(unsigned int value)
    {
        *reinterpret_cast<unsigned int*>(address) = value;
    }
};

 template<auto address>
 class RCCBase
 {
 private:

     static constexpr auto cr_address = address + 0x00;
     static constexpr auto pllcfgr_address = address + 0x04;

 public:

     struct CR : public Register<cr_address>
     {
     };

     struct PLLCFGR : public Register<pllcfgr_address>
     {
     };

 };

// Только для vs. В IAR подставить конкретный адрес.
extern unsigned int ext_rcc[128];

using RCC = RCCBase<ext_rcc>;

И следующий код:

main.cpp

#include "RCC.h"

// Только для vs
u32 ext_rcc[128] = { 0 };

int main(void)
{
    RCC::CR::Set(0);
    RCC::PLLCFGR::Set(0);

    return 0;
}

Проблема что первая строчка RCC::CR::Set(0); выполняется как положено, а следующая при компиляции создает ошибку: Ошибка C2975 address_: недопустимый аргумент шаблона для "Register", требуется константное выражение времени компиляции

Не понимаю, почему в классе RCCBase cr_address остается константой времени компиляции, pllcfgr_address из-за сложения перестает ею быть. Пробовал такое:

static constexpr auto offset = 0x04;
static constexpr auto pllcfgr_address = address + offset;

Та же самая ошибка. В чем дело-то?

Проект собран как консольное приложение в VS2019 со стандартом C++17

Лог сборки:

Сборка начата…
1>------ Сборка начата: проект: ConsoleApplication2, Конфигурация: Debug x64 ------
1>main.cpp
1>C:\Users\fedorov_dn\source\repos\ConsoleApplication2\ConsoleApplication2\RCC.h(29): error C2975: address: недопустимый аргумент шаблона для "Register", требуется константное выражение времени компиляции
1>C:\Users\fedorov_dn\source\repos\ConsoleApplication2\ConsoleApplication2\RCC.h(3): message : см. объявление "address"
1>C:\Users\fedorov_dn\source\repos\ConsoleApplication2\ConsoleApplication2\main.cpp(9): message : выполняется компиляция ссылки на экземпляр класс шаблон функции "RCCBase<& ext_rcc>::PLLCFGR"
1>Сборка проекта "ConsoleApplication2.vcxproj" завершена с ошибкой.
========== Сборка: успешно: 0, с ошибками: 1, без изменений: 0, пропущено: 0 ==========

Ответы (1 шт):

Автор решения: user7860670

минимальный воспроизводимый пример:

template<auto x_address>
struct Foo {};

char bar[8]{};
Foo<bar + 0> a{};
Foo<bar + 4> b{};

online compiler

при сборке с флагами /std:c++17 /permissive- /diagnostics:caret получаем

<source>(6,12): error C2975: 'x_address': invalid template argument for 'Foo', expected compile-time constant expression
Foo<bar + 4> b{};
           ^
<source>(1): note: see declaration of 'x_address'
template<auto x_address>

По стандарту параметр шаблона не-тип не может ссылаться на подобъект, которым является элемент массива:

[temp.arg.nontype]
2 A template-argument for a non-type template-parameter shall be a converted constant expression (8.20) of the type of the template-parameter. For a non-type template-parameter of reference or pointer type, the value of the constant expression shall not refer to (or for a pointer type, shall not be the address of):
— (2.1) a subobject (4.5),
— (2.2) a temporary object (15.2),
— (2.3) a string literal (5.13.5),
— (2.4) the result of a typeid expression (8.2.8), or
— (2.5) a predefined func variable (11.4.1).

[intro.object]
2 Objects can contain other objects, called subobjects. A subobject can be a member subobject (12.2), a base class subobject (Clause 13), or an array element.

Что делать? Передавать смещение от базового адреса в качестве еще одного параметра шаблона.

→ Ссылка