I have a template class which takes as its first template argument a foo * pointer. I'd like to instantiate one of these with a foo located at an absolute address, like so:
class foo
{
int baz;
};
template<foo *f> class bar
{
public:
bar() {}
void update() { /* ... */ }
};
// ....
#define FOO_ADDR ((foo *)0x80103400)
#define FOO_NULL ((foo *)0)
foo testFoo;
bar<FOO_ADDR> myFoo; // fails with non-integral argument
bar<FOO_NULL> huh; // compiles, I was surprised by this
bar<&testFoo> test; // compiles as expected (but not useful)
Does anyone know if it's possible without resorting to the linker and getting FOO_ADDR to be defined with external linkage?
This is with the Keil ARM C/C++ Compiler version V5.06 update 1 (build 61), I've tried switching on C++11 mode but (apart from throwing a load of new errors in the system headers) it didn't change the behaviour.
Update: here's the proposed solution (with the real code this time) using int casts
template<uint32 PORT, uint32 BIT, uint32 RATE> class LedToggle
{
uint32 mTicks;
uint32 mSetReset;
public:
LedToggle()
{
mTicks = 0;
mSetReset = 1 << BIT;
}
void Update()
{
uint32 mask = ((mTicks++ & RATE) - 1) >> 31;
((GPIO_TypeDef *)PORT)->BSRR = mSetReset & mask;
mSetReset ^= ((1 << BIT) | (1 << (BIT + 16))) & mask;
}
};
LedToggle<(uint32)GPIOC, 13, 1023> led;
It's pretty ugly, but it does work. I'd be interested to hear if anyone can improve on it?
The declaration bar<(foo*)0x80103400> myFoo; is ill-formed because non-type template arguments must be a constant expression, from [temp.arg.nontype]:
A template-argument for a non-type template-parameter shall be a converted constant expression (5.20) of the type of the template-parameter.
And the argument you are passing is not, from [expr.const]:
A conditional-expression e is a core constant expression unless the evaluation of e, following the rules of the
abstract machine (1.9), would evaluate one of the following expressions:
— [...]
— a reinterpret_cast (5.2.10);
— [...]
The declaration bar<(foo*)0> huh works since it does not involve a cast, it's simply a null pointer of type foo* (0 is special) and so it is a valid constant expression.
You could instead simply pass in the address as a template non-type parameter:
template <uintptr_t address>
struct bar { ... };
bar<0x8013400> myFooWorks;
That is viable.
Facing the same problem (on an STM32), as a work-around I found function pointer template parameters, like so:
template<GPIO_TypeDef* PORT(), uint32 BIT, uint32 RATE>
class LedToggle
{
public:
void Update()
{
// ...
PORT()->BSRR = mSetReset & mask;
// ...
}
};
constexpr GPIO_TypeDef* Port_C() {
return PORTC;
}
LedToggle<Port_C, 13, 1023> led;
Notice that we use a function pointer as template parameter, to a function that returns the desired actual pointer. Inside that function casts are allowed; and since the function is declared constexpr the compiler may (should) optimize away the actual function call and use the function's return value like a literal.
Casting to/from ints works, but as pointed out, it's dangerous. Another solution similar to JimmyB's is to use enum classes instead of function pointers. The enum class member values are set to the device addresses as specified inthe vendor-supplied header. For instance, for the STM32 series, ST provides a header with the following defined:
// Vendor-supplied device header file (example)
#define GPIOA_BASE = 0x40001000
#define GPIOB_BASE = 0x40002000
// etc...
In your code, create an enum class:
#include <vendor-supplied-device-header.h>
enum class GPIO : uint32_t {
A = GPIOA_BASE,
B = GPIOB_BASE,
C = GPIOC_BASE,
D = GPIOD_BASE,
E = GPIOE_BASE,
F = GPIOF_BASE,
G = GPIOG_BASE,
#ifdef GPIOH_BASE //optional: wrap each member in an #ifdef to improve portability
H = GPIOH_BASE,
#endif
//.. etc
};
To avoid multiple messy casts, just do it once in the class using a private method. For example then your LedToggle class would be written like this:
template<GPIOPORT PORT, uint8_t PIN, uint32_t RATE> class LedToggle
{
static_assert(PIN < 15, "Only pin numbers 0 - 15 are valid");
volatile auto GPIOPort(GPIOPORT PORT) {
return reinterpret_cast<GPIO_TypeDef *>(port_);
}
uint32_t mTicks;
uint32_t mSetReset;
public:
LedToggle()
{
mTicks = 0;
mSetReset = 1 << PIN;
}
void Update()
{
uint32 mask = ((mTicks++ & RATE) - 1) >> 31;
GPIOPort(PORT)->BSRR = mSetReset & mask;
mSetReset ^= ((1 << PIN) | (1 << (PIN + 16))) & mask;
}
};
LedToggle<GPIO::C, 13, 1023> led;
The benefit of this method is that the class users are forced to use only members of the GPIO enum class, therefore invalid addresses are prohibited.
You can use enum classes for any of the template parameters, for instance you could replace the PIN parameter with an enum class whose members are set to the vendor's specified GPIO_PIN_1, GPIO_PIN_2, etc. Then you'd write:
LedToggle<GPIO::C, Pin::_13, 1023>
From the C++11 Standard (emphasis mine):
14.3.2 Template non-type arguments
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
— the name of a non-type 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
— a constant expression that evaluates to a null pointer value (4.10); or
When compiled with g++ -Wall, I get the following error:
error: ‘2148545536u’ is not a valid template argument for ‘foo*’ because it is not the address of a variable
bar<FOO_ADDR> myFoo; // fails with non-integral argument
^
It seems that the compiler is able to detect that 0x80103400 is not the address of a variable, it's just a constant expression.
Have you try casting the pointer address to and from uintptr_t, which is an unsigned integer capable of holding a pointer value?
The type is defined in a standard header <cstdint> but it is only optional. If it does not exist in your version of C++, try size_t instead.
A full example would then look like:
#include <cstdint>
class foo
{
int baz;
};
template<uintptr_t addr> class bar
{
constexpr static const foo* f = (foo*)(addr);
public:
bar() {}
void update() { }
};
#define FOO_ADDR ((uintptr_t)0x80103400)
int main() {
bar<FOO_ADDR> myFoo;
}
The obvious drawback is that there is no typechecking at the template parameter. You pass a value which will hopefully refer to foo object and not a different one.
Not to mention that we are in the undefined behavior world as far as the standard goes....
You seem to be able to compile with the line
constexpr static const foo* f = reinterpret_cast<foo*>(addr);
with at least some of the compilers as well (http://coliru.stacked-crooked.com/a/5af62bedecf2d75a)
If your compiler rejects casting in the context of constexpr as it is ill-formed (as per Barry's comment) you can define it as a regular static const variable:
template<uintptr_t addr>
class bar
{
static const foo* f;
public:
bar() {}
void update() { }
};
template<uintptr_t addr>
const foo* bar<addr>::f = reinterpret_cast<foo*>(addr);
Less ideal but solves that problem hopefully.
First, don't use c-style casts. It doesn't make it explicit what is does.
Second, you will realize that in order to cast an arbitrary number into a pointer, you need to use reinterpret_cast. This sort of cast is not allowed in constexpr expressions.
Since template parameters are only possible with constant expressions, an arbitrary number as a pointer is not possible.
The case where 0 is possible is because 0 is convertible to nullptr, which is constant expression.
Related
Maybe the title is not clear, so concretely:
#include <type_traits>
template<typename T>
constexpr int test(T)
{
return std::is_integral<T>::value;
}
int main()
{
constexpr int a = test(1); // right
constexpr int b = test(1.0); // right
int c = 2;
constexpr int d = test(c); // ERROR!
return 0;
}
In fact, the function doesn't use anything but the type of the parameter, which can be determined obviously in the compilation time. So why is that forbidden and is there any way to make constexpr get the value when only the type of parameter is used?
In fact, I hope to let users call the function through parameters directly rather than code like test<decltype(b)>, which is a feasible but not-convenient-to-use way, to check if the types of parameters obey some rules.
Just take T by reference so it doesn't need to read the value:
template<typename T>
constexpr int test(T&&)
{
return std::is_integral<std::remove_cvref_t<T>>::value;
}
You can even declare test with consteval, if you want to.
(Note that stripping cv-qualifiers isn't necessary in this instance; cv-qualified integral types satisfy the std::is_integral trait.)
Why can't constexpr be used for non-const variables when the function only uses the types?
Because the call expression test(c) is not a constant expression and hence it cannot be used as an initializer for d.
Basically, for the call expression test(c) to be a constant expression, c must be a constant expression. It doesn't matter whether c is used or not inside the function itself. This is why, the call expressions test(1) and test(1.0) works and can be used as an initializer for a and b respectively.
The C++11 decltype returns the type of the expression given to it (mostly). But this can differ from the type of the expression as it is actually accessible:
template<typename T>
struct Ref {
Ref(T&) { }
};
#define GETTYPE decltype
//#define GETTYPE typeof
struct Problem {
void doit_c() const { Ref<GETTYPE(n)> rn{n}; }
void doit_nc() { Ref<GETTYPE(n)> rn{n}; }
int n;
};
int main() {
int i;
const int ci = 0;
Problem pr;
// decltype == typeof == int
Ref<GETTYPE(i)> ri{i};
pr.doit_nc();
// decltype == typeof == const int
Ref<GETTYPE(ci)> rci{ci};
Ref<GETTYPE(static_cast<const int&>(i))> rcci{static_cast<const int&>(i)};
// typeof == const int, decltype == int (!)
pr.doit_c();
return 0;
}
In the example, the Ref struct is just used to cause a compile error if T does not match the actual constructor argument. The Problem::doit_c() method is where decltype(n) returns a non-const result, even though n is const in this context.
If one switches from the standard decltype to the GNU extension typeof, this seems to take the const-ness of the method into account.
Now my question: Is there a C++11 / C++14 / C++17 compliant alternative to decltype() / typeof() that behaves "correctly" (as in: no compile error above) for expressions like the declaration in the const-method above?
Edited:
Simplified the first sentence to remove some errors and stop distracting from the point of the question (thanks, #skypjack)
Simplified the use use of macros in the example code (thanks, #Richard Critten)
decltype is a feature that kinda sits at two chairs at once. Firstly, as the name suggests, it can give you the exact declared type of an entity, ignoring the context in which it is used. Secondly, it can treat its argument as an expression, whose exact type depends on the context and its value category.
decltype applied directly to a "naked" (unparenthesized) class member access is a special case, in which decltype acts in accordance with its first role. It will not treat n as an expression. Instead it will produce the type of that class member, ignoring the context.
If you want it to treat n as an expression, you have to parenthesize it
struct Problem {
void doit_c() const
{
Ref<decltype(n)> rn1{n}; // `decltype(n)` is `int` -> ERROR
Ref<decltype((n))> rn2{n}; // `decltype((n))` is `const int &` -> compiles OK
}
};
You can find out the effective cv-qualified type of n using a temporary reference:
void doit_c() const { auto& x = n; Ref<GETTYPE(x)> rn{n}; }
void doit_nc() { auto& x = n; Ref<GETTYPE(x)> rn{n}; }
But it's simpler and clearer to parenthesize, as shown in AnT's answer.
Here is what I read: using alias for static member functions?
In the answer I see a suggestion to use constexpr. What is the reason to use constexpr for void functions.
Please demonstrate a simple use case. I am new to constexpr so in complex examples I will not understand the gist.
Rahul's answer cites the standard paragraph which allow void constexpr functions, but it doesn't give a use-case. One use-case that comes to my mind would be to have a constexpr class, and as usual factor out behavior common to method in helper methods. The standard explicitly mentions function doing checks, e.g. assertions. I don't have a concrete example at hand, but I can imagine something like
class A
{
public:
constexpr X doSomething(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
constexpr X doSomethingElse(Y arg1) {
checkInvariant();
constraintOnYArgument(arg1);
// ...
checkInvariant();
}
private:
constexpr void constraintOnYArguments(Y arg) {
}
constexpr void checkInvariant() {
// some checks
if (!some condition) {
throw std::logic_error("Oh no!");
}
}
};
As per the C++ 14 standard, void is a literal type
A type is a literal type if it is:
— void; or
— a scalar type; or
— a reference type; or
— an array of literal type; or
— a class type (Clause 9) that has all of the following properties: —
it has a trivial destructor,
— it is an aggregate type (8.5.1) or has at least one constexpr
constructor or constructor template that is not a copy or move
constructor, and
— all of its non-static data members and base classes are of
non-volatile literal types.
From here:
An arbitrary expression-statement is permitted, in order to allow
calls to functions performing checks and to allow assert-like
constructs. void also becomes a literal type, so that constexpr
functions which exist only to perform such checks may return void.
A reasonable use case is the manipulation of volatile variables. The following is a very simplified case from embedded programming using GNU tools (g++, ld):
To make an address of a peripheral a constexpr, you need to put it at a fixed location. This must be done in a linker script:
⋮
/* Define output sections */
SECTIONS
{
GPIO 0x48000000 (NOLOAD) : { *(.GPIO) }
⋮
Now, the .GPIO section is at the fixed address 0x48000400. Peripherals can be modeled by PODs containing volatile members. In the following example, the POD is named gpio_t and has just a single member: mode. The member can be set up in a constexpr function. Of course, there is no benefit to use a function to set a variable to a constant value. But in real use cases values and addresses have to be calculated. Think, e.g., of setting a divider for a Baud rate.
struct gpio_t {
volatile std::uint32_t mode;
};
__attribute__ ((section (".GPIO"))) gpio_t Gpio = {0};
static constexpr gpio_t *port {&Gpio};
static constexpr void init () {
port->mode = 42u;
};
void main {
init ();
⋮
};
Note: The C-style idiom of casting integers to addresses does not work because it reinterpret_cast<> does not qualify for creating constexpr pointers (see Since C++14 illegal). The following fails:
constexpr gpio_t *port {(gpio_t *) 0x48000400};
As long as parameter number is an integral constant, this constexpr version will compute the result at compile-time (C++11 compilers only). And when the number is a run-time integer, this same function is perfectly capable of computing the result at run-time. So you don't need two different versions of the same program: one for compile-time and another for run-time. One implementation does it all.
In C++11, is there a clean way to disable implicit conversion between typedefs, or do you have to do something nasty like wrap your int in a class and define and delete various operators?
typedef int Foo;
typedef int Bar;
Foo foo(1);
Bar bar(2);
bar = foo; // Implicit conversion!
HelloWorld explains why what you have cannot work. You'll need what's typically called a "strong" typedef to do what you want. An example implementation is BOOST_STRONG_TYPEDEF:
#include <boost/serialization/strong_typedef.hpp>
BOOST_STRONG_TYPEDEF(int, a)
void f(int x); // (1) function to handle simple integers
void f(a x); // (2) special function to handle integers of type a
int main(){
int x = 1;
a y;
y = x; // other operations permitted as a is converted as necessary
f(x); // chooses (1)
f(y); // chooses (2)
}
If we had done typedef int a;, then the code would be ambiguous.
The C++ standard says:
7.1.3 The typedef specifier
A name declared with the typedef specifier becomes a typedef-name. Within the scope of its declaration, a typedef-name is syntactically equivalent to a keyword and names the type associated with the identifier in
the way described in Clause 8. A typedef-name is thus a synonym for another type. A typedef-name does
not introduce a new type the way a class declaration (9.1) or enum declaration does
But e.g. class or struct introduce new types. In the following example uniqueUnused does actually nothing but is used to create a different type Value<int, 1> != Value<int, 2>. So maybe this is something you are looking for. Keep in mind there is no guarantee the compiler gets rid of the outer structure! The only guarantee this code gives you it's the same size as int
template<typename T, int uniqueUnused>
struct Value
{
Value() : _val({}) {}
Value(T val) : _val(val) { }
T _val;
operator T&() { return _val; }
// evaluate if you with or without refs for assignments
operator T() { return _val; }
};
using Foo = Value<int, 1>;
using Bar = Value<int, 2>;
static_assert(sizeof(Foo) == sizeof(int), "int must be of same size");
static_assert(sizeof(Bar) == sizeof(int), "int must be of same size");
If you want to create a new type based on a class you can simply go with this example (this doesn't work with scalar types since you can't inherit from ints):
class Foo : public Bar // introduces a new type called Foo
{
using Bar::Bar;
};
I wanted to do something similar to keep different indexes separated not only logically, but also enforced by the compiler. The solution I came up with is basically to just define structs with one element. In some ways it's more painful to use, but it works very well with my situation since I often don't need to deal with the actual value of the index for a lot of my code, just passing it around.
typedef struct{uint16_t i;} ExpressionIndex;
typedef struct{uint16_t i;} StatementIndex;
Now, trying to do
ExpressionIndex foo() {
StatementIndex i;
return i;
}
yields the error error: incompatible types when returning type ‘StatementIndex’ but ‘ExpressionIndex’ was expected
Converting between types is a bit painful, but that was the intent of my change.
ExpressionIndex exp = (ExpressionIndex){stmt.i};
It's not strict type-checking, but illegal conversions can made visible by using original, or Apps Hungarian Notation (H. N.). If you think H. N. means name-type-as-prefix, you're wrong (it's System H. N., and it's, hm, unnecessary naming overhead).
Using the (Apps) H. N., the variable prefix marks not the type (e.g. int), but the purpose, e.g. counter, length, seconds etc. So, when you add a counter to a variable contains elapsed time, you write cntSomethingCounter + secElapsedSinceLastSomething, and you can see that it smells. Compiler does not alerts, but it pokes your eyes.
Read more: http://www.joelonsoftware.com/articles/Wrong.html
I have a class with static const members that I'm initializing inside the class declaration:
#include <iostream>
class Foo
{
public:
static const int i = 9;
static const float f = 2.9999;
};
int main()
{
std::cout << Foo::i << std::endl;
std::cout << Foo::f << std::endl;
return 0;
}
When compiled with GCC 4.8.2 with option --std=c++11, it gives this compile error:
foo.cpp:7:32: error: ‘constexpr’ needed for in-class initialization of static data member ‘const float Foo::f’ of non-integral type [-fpermissive]
static const float f = 2.9999;
^
As the message indicates, the error goes away if the line is changed to static constexpr float f = 2.9999;.
Why should the in-class static const initialization of a floating-point variable be any different from a integral variable? Aren't they both just a value of certain size (number of bytes) that is copied over (like a macro) or referred to using a pointer?
Some older answers to similar (not the same) questions on SO indicate that this is because floating point expressions might give different results between the compiled machine and the execution machine (assuming a cross-compilation scenario).
However:
the above code assigns a value directly, there is no arithmetic operation that needs to be performed to compute a value
there might be different results for integral expressions too since its underflow and overflow results are not unambiguously defined across different architectures.
Finally, what magic does constexpr do here that const does not? Why doesn't the language just do what constexpr does when const is used? I mean, why another keyword when the following statements work fine as C++ code outside a class anyway:
const int i = 9;
const float f = 2.9999;
It's just a limitation of the language, and one that has been addressed by the introduction of generalized constant expressions.
Since the original C++, only static class member constants of integral type can be initialized inline; this is the is same type restriction as for non-type template parameters. So you can combine the two like this:
struct MyTrait { static const int value = 10; };
template <int N> struct Foo;
Foo<MyTrait::value> foo;
In this usage, the static constant is not odr-used and no definition is required. I'm speculating, but I can imagine that this kind of use was the primary intention of allowing inline initialization. For all other types, you would presumably want to have a definition anyway, so you might as well put the initializer in the definition.
This isn't an excuse, of course, and I suppose the introduction of constexpr seeks to rectify this original narrow-mindedness.