gpt4 book ai didi

c++ - 基于硬件寄存器的非类型模板参数

转载 作者:太空狗 更新时间:2023-10-29 23:06:14 26 4
gpt4 key购买 nike

我正在使用 STM32 的硬件定时器与许多光学编码器连接。我想创建一个模板化类,它提供了一个方便的接口(interface)来与硬件定时器交互。定时器寄存器是内存映射的,它们的地址在制造商提供的与设备数据表匹配的 header 中#defined。模板参数实际上是定时器外设的基本内存地址。下面是我目前正在尝试做的一个最小工作示例:

#include <cstdint>

// Effectively supplied by chip manufacturer headers
struct timer_peripheral {
volatile uint32_t count;
// ... lots of other registers ...
};
// Also supplied by chip manufacturer headers
#define TIM1 ((timer_peripheral *) 0x40000000)
#define TIM2 ((timer_peripheral *) 0x40000400)
// My templated class
template <timer_peripheral * Timer>
class OpticalEncoderCounter {
OpticalEncoderCounter();
};

template <timer_peripheral * Timer>
OpticalEncoderCounter<Timer>::OpticalEncoderCounter()
{
}

int main()
{
// option 1
OpticalEncoderCounter<TIM1> encoder0;

// option 2
timer_peripheral * t = TIM2;
OpticalEncoderCounter<t> encoder1;
}

但是,当我编译时,我使用 g++-4.7.2 -std=c++11 得到这些错误:

错误|无法将模板参数“1073742848u”转换为“timer_peripheral*”

错误| “t”不是有效的模板参数,因为“t”是一个变量,而不是变量的地址

在阅读了有关非类型模板参数的内容后,我仍然不确定如何解决我的问题以及是否可以按照我的想法使用模板。我在选项 1 中尝试了 static_cast 和 reinterpret_cast,但似乎没有任何区别。

最佳答案

精简版

模板非类型参数必须是常量表达式。 ((timer_peripheral *) 0x40000000) 包含指向指针类型的 reinterpret_cast,因此您不能在常量表达式中使用它。


C++03

[temp.arg.nontype]/1

A template-argument for a non-type, non-template template-parameter shall be one of:

  • an integral constant-expression of integral or enumeration type; or
  • [...]
  • the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
  • [...]

所以我们必须使用整数常量表达式。

[expr.const]/1

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. [...] Only type conversions to integral or enumeration types can be used.

((timer_peripheral *) 0x40000000) 包含对指针类型的转换,因此它不能出现在整型常量表达式中。


C++11

[temp.arg.nontype]/1

A template-argument for a non-type, non-template template-parameter shall be one of:

  • for a non-type template-parameter of integral or enumeration type, a converted constant expression (5.19) of the type of the template-parameter; or
  • [...]
  • a constant expression (5.19) that designates the address of an object with static storage duration and external or internal linkage or a function with external or internal linkage, including function templates and function template-ids but excluding non-static class members, expressed (ignoring parentheses) as & id-expression, except that the & may be omitted if the name refers to a function or array and shall be omitted if the corresponding template-parameter is a reference; or
  • [...]

我们不能使用“设计地址...”的常量表达式,但我们可以使用转换后的常量表达式吗?

[expr.const]/2

A conditional-expression is a core constant expression unless it involves one of the following [...]

  • [...]
  • a reinterpret_cast (5.2.10);
  • [...]

没有。不可能。


解决方法

使用函数模板返回指针。

#include <cstdint>

// Effectively supplied by chip manufacturer headers
struct timer_peripheral {
volatile uint32_t count;
// ... lots of other registers ...
};

#define TIM1 ((timer_peripheral *) 0x40000000)
#define TIM2 ((timer_peripheral *) 0x40000400)

enum TIMS { tim1, tim2 };

template < TIMS tim >
inline timer_peripheral* get_timer_address()
{
static_assert(tim && false, "unknown timer identifier");
return nullptr;
}
template <>
inline timer_peripheral* get_timer_address < tim1 >()
{
return TIM1;
}
template <>
inline timer_peripheral* get_timer_address < tim2 >()
{
return TIM2;
}

// My templated class
template < TIMS tim >
class OpticalEncoderCounter {
static timer_peripheral* get() { return get_timer_address<tim>(); }

public:
OpticalEncoderCounter();
};

template < TIMS tim >
OpticalEncoderCounter<tim>::OpticalEncoderCounter()
{
}

int main()
{
OpticalEncoderCounter<tim1> encoder0;
}

关于c++ - 基于硬件寄存器的非类型模板参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16575534/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com