gpt4 book ai didi

c++ - static_assert 始终计算为真(avr、g++)

转载 作者:行者123 更新时间:2023-11-28 05:26:59 25 4
gpt4 key购买 nike

我的 avr 设备上有一些用于计时器抽象的模板代码。这里最相关的部分是:

template <typename T>
class Timerx8bit
{
T reg;

static_assert(T::res == TimerResolution::bit8, "The timer template is 8bit, registers must also be 8bit");
}


struct Timer0
{
constexpr static const TimerResolution res = TimerResolution::bit16;

volatile uint8_t* tccra = &TCCR0A;
volatile uint8_t* tccrb = &TCCR0B;
//[...]
};

现在我将 Timer0 提供给模板。该代码的问题是,静态断言似乎总是评估为真,尽管在上述情况下它应该失败。 TimerResolution 只是一个枚举类。

问题似乎出在模板中,如果我将“TimerResolution::bit8 != TimerResolution::bit8”作为条件,编译会按预期失败,但“T::res != T::res”会编译没有任何问题......我在这里错过了什么?

编辑:在准备完整的代码示例时,我发现了问题所在,尽管我仍然不太明白为什么会这样。一、代码:

enum class TimerResolution_test
{
bit8,
bit16
};

struct Timer0_test
{
constexpr static const TimerResolution_test res = TimerResolution_test::bit8;
};

template <typename T>
class Timerx8bit_test
{
public:
constexpr static const TimerResolution_test res = TimerResolution_test::bit8;

private:
T reg;

static_assert(T::res != T::res, "The timer template is 8bit, registers must also be 8bit");
};

template<typename Timer>
class pwm_test
{

};

实例化:

pwm_test<Timerx8bit_test<Timer0_test>> testTimer; // Compiles
Timerx8bit_test<Timer0_test> testTimer2; // Fails

第二个实例化失败,出现上面的 static_assert。如果我使用“false”而不是模板化条件,它在这两种情况下都会失败……这是为什么呢?在原始模板条件下,这两种情况不应该都失败吗?

最佳答案

模板不需要立即完成类型定义(想想 CRTP)。他们必须使用类型的方式导致需要完整的类型定义。您的 pwm_test 不使用除名称外给定的类型参数。因此模板主体永远不需要实例化。

在第二种情况下,您创建了一个对象,因此自然会发生模板主体实例化。

因此您需要通过提供必须发生的上下文来强制实例化:

template<typename Timer>
class pwm_test
{
enum { _ = sizeof(Timer) };
};

与此相关,如果您在模板的成员函数中有任何静态断言,这些断言将不会被触发,直到您在代码中添加对该函数的调用。


要回答您的另一个问题,为什么 static_assert 在一种情况下会立即导致错误,而在另一种情况下不会:

§14.6/8 [温度.res]

Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if:

  • ...
  • a hypothetical instantiation of a template immediately following its definition would be ill-formed due to a construct that does not depend on a template parameter, or

因此,当在解析模板时遇到 static_assert(false) 时,编译器可以推断出所有模板实例化都是病式的。在这种情况下,它会选择立即发出诊断(请注意,它不是必须的)。

当遇到 static_assert(T::res != T::res) 时,编译器会检查语法,但无法推断出 T::res != T::res 始终为 false,该信息仅在 T 已知时可用(毕竟,T::res 可能会重载 operator! = 总是返回 true)。

关于c++ - static_assert 始终计算为真(avr、g++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40344285/

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