I have the following code:
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
}
How can I instantiate this template?
I can do this:
Port port;
int main() {
PortWrapper<&port> port1;
}
But that's not what I need. I need port to be mapped to predefined constant address.
8. Why we use :: template-template parameter? Explanation: It is used to adapt a policy into binary ones.
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
Template non-type arguments in C++It is also possible to use non-type arguments (basic/derived data types) i.e., in addition to the type argument T, it can also use other arguments such as strings, function names, constant expressions, and built-in data types.
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
You can't as-is, because non-type template arguments of pointer type can only be null pointer expressions or addresses of objects, and a conversion from an integer is neither of those.
You could redesign the template slightly:
template <uintptr_t portAddr>
class PortWrapper {
private:
static constexpr Port* port() { return (Port*)portAddr; }
public:
PortWrapper() {
port()->reg1 = 1;
port()->reg2 = 2;
}
};
Note that in the comments, @KonradRudolph disputes whether this strictly follows the rules for a constexpr
function, and it's quite possible it does not. Nevertheless, even if constexpr
is omitted from the above, any decent compiler will inline the call of port()
, effectively resulting in compile-time evaluation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With