6

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.

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

11 Comments

Since when can a reinterpret_cast be a constexpr? Is this C++14? (I mean, sure, this will compile, but the result will not evaluate at compile time)
@KonradRudolph You're right, it needs a C-style cast. Amended. I'm stuck with VS2010, so I'm not up to full speed with constexpr rules. And I'd say that regardless of whether it fits the definition of constexpr, any decent compiler will evaluate that in compile time.
@Angew Actually as far as I know no cast is allowed here.
@KonradRudolph A C-style cast is not explicitly prohibited in a core-constant-expression. So it really depends on whether the result of the cast "evaluates to the address of an object with static storage duration." Probably not, but since "no diagnostic is required," it might Do The Right Thing anyway.
@Angew “no diagnostic required” never means “do the right thing”, it means that the compiler is allowed to let it fail silently.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.