我有以下代码:
struct Port {
int reg1;
int reg2;
};
#define PORT1 ((Port *) 0x00010000); // absolutely compile-time constants
#define PORT2 ((Port *) 0x00020000);
template <Port * port>
class PortWrapper {
public:
PortWrapper() {
port->reg1 = 1;
port->reg2 = 2;
}
};
constexpr static const Port * const port1c = PORT1;
int main(int argc, char* argv[]) {
PortWrapper<PORT1> port1; //Compiler says: error: could not convert template argument '65536u' to 'Port*'
PortWrapper<port1c> port1; //Compiler says: error: 'port1c' is not a valid template argument because 'port1c' is a variable, not the address of a variable
}
如何实例化此模板?
我可以这样做:
Port port;
int main() {
PortWrapper<&port> port1;
}
但这不是我需要的。我需要将端口映射到预定义的常量地址。
答案 0 :(得分:2)
您可以按原样,因为指针类型的非类型模板参数只能是空指针表达式或对象的地址,并且从整数转换不是那些。
您可以稍微重新设计模板:
template <uintptr_t portAddr>
class PortWrapper {
private:
static constexpr Port* port() { return (Port*)portAddr; }
public:
PortWrapper() {
port()->reg1 = 1;
port()->reg2 = 2;
}
};
请注意,在评论中,@ KonradRudolph对这是否严格遵循constexpr
函数的规则进行了争议,并且它很可能不会。尽管如此,即使从上面省略constexpr
,任何体面的编译器都会内联port()
的调用,从而有效地进行编译时评估。