Type Punning via constexpr union - c++

I am maintaining an old code base, that is using a union of an integer type with a bit-field struct for type-punning. My compiler is VS2017. As an example, the code is similar to the following:
struct FlagsType
{
unsigned flag0 : 1;
unsigned flag1 : 1;
unsigned flag2 : 1;
};
union FlagsTypeUnion
{
unsigned flagsAsInt;
FlagsType flags;
};
bool isBitSet(unsigned flagNum, FlagsTypeUnion flags)
{
return ((1u << flagNum) & flags.flagsAsInt);
}
This code has a number of undefined behavior issues. Namely, it is hotly debated whether type punning is defined behavior or not, but on top of that, the implementation of packing bit-fields is implementation-defined. To address these issues, I would like to add static-assert statements to validate that the VS implementation enables using this type of approach. However, when I tried to add the following code, I get error C2131: expression did not evaluate to a constant.
union FlagsTypeUnion
{
unsigned flagsAsInt;
FlagsType flags;
constexpr FlagsTypeUnion(unsigned const f = 0) : flagsAsInt{ f } {}
};
static_assert(FlagsTypeUnion{ 1 }.flags.flag0,
"The code currently assumes bit-fields are packed from LSB to MSB");
Is there any way to add compile-time checks to verify the type-punning and bit-packing code works as the runtime code is assuming? Unfortunately, this code is spread throughout the code base, so changing the structures isn't really feasible.

You might use std::bit_cast (C++20):
struct FlagsType
{
unsigned flag0 : 1;
unsigned flag1 : 1;
unsigned flag2 : 1;
unsigned padding : 32 - 3; // Needed for gcc
};
static_assert(std::is_trivially_constructible_v<FlagsType>);
constexpr FlagsType makeFlagsType(bool flag0, bool flag1, bool flag2)
{
FlagsType res{};
res.flag0 = flag0;
res.flag1 = flag1;
res.flag2 = flag2;
return res;
}
static_assert(std::bit_cast<unsigned>(makeFlagsType(true, false, false)) == 1);
Demo
clang doesn't support it (yet) though.
gcc requires to add explicitly the padding bits for the constexpr check.

Related

Mapping a structure to uint64_t

What is the right way to convert the structure below to uint64_t?
struct Data
{
uint64_t sign : 1;
uint64_t exp : 4;
uint64_t man : 8;
};
static_assert(sizeof(Data) == sizeof(uint64_t));
the obvious one is
Data data;
uint64_t n = *(reinterpret_cast<const uint64_t*>(&data));
but it does not compile as constexpr and produces the following warnings in GCC:
dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
EDIT1:
The value of resulting uint64_t may be different with different compilers. But the value of Data structure should be the same when I convert it back from uint64_t.
So, saying more exactly I need:
Data data;
uint64_t n = convert(data);
Data data2 = convert_back(n);
static_assert(data == data2);
You std::memcpy the structure to an uint64_t. std::memcpy is a legal way to perform type punning, it is allowed since your structure is trivially-copyable.
In C++20 there is also std::bit_cast.
Unlike std::memcpy it's constexpr, but to make it work at compile-time I had to add uint64_t : 51; at the end of the struct.
Interestingly, Clang (unlike GCC and MSVC) refused to perform it at compile-time:
note: constexpr bit_cast involving bit-field is not yet supported
The conversion is not "obvious" because the exact layout of Data is implementation defined (see bit field). Moreover, your cast via pointers breaks strict aliasing, as the error suggests. There is no uint64_t stored at the adress of data.
You can convert it like this:
constexpr uint64_t Data_2_uint(const Data& d){
return d.sign + (d.exp << 1) + (d.man << 5);
}
If you are looking for an implicit conversion, you may use union to access the same data structure with a different alias
union Data {
struct {
uint64_t sign : 1;
uint64_t exp : 4;
uint64_t man : 8;
}
uint64_t data_as_uint64;
}
To make sure you don't have memory representation problems with padding of the fields, you should use #pragma pack, and set the packing to 1
#pragma pack(push, 1)
union Data {
struct {
uint64_t sign : 1;
uint64_t exp : 4;
uint64_t man : 8;
}
uint64_t data_as_uint64;
}
#pragma pack(pop)
Notice that #pragma pack is compiler dependent, and you need to make sure your compiler supports it.

MSVC throws error when bitfield is bigger than underlying type. Is that standard conform? [duplicate]

The following code generates MSVS Compiler Error C2034 in Visual Studio 2008:
struct TestStruct {
unsigned short var1 : 7;
unsigned short : 9;
bool var2 : 1;
bool : 15; // C2034
};
error C2034: 'TestStruct::<alignment member>': type of bit field too small for number of bits
However, the following code compiles successfully, which seems kind of silly, because I'd think the compiler could have just done this automatically:
struct TestStruct {
unsigned short var1 : 7;
unsigned short : 9;
bool var2 : 1;
bool : 7;
bool : 8;
};
However, both code snippets compile on my Linux GCC compiler. Is one compiler more correct than the other, according to the C++ Standard? If so, which, and why?
Yes this is a bug in MSVS. That standard states in [class.bit]/1
[...]The value of the integral constant expression may be larger than the number of bits in the object representation (3.9) of the bit-field’s type; in such cases the extra bits are used as padding bits and do not participate in the value representation (3.9) of the bit-field.[...]
So the compiler should have added extra padding and only let you have a number of bits equal to CHAR_BIT * sizeof(bit_field_underlying_type).

How can I refer to sub-elements in a particular variable?

My problem is as follows: I have a 64 bit variable, of type uint64_t (so I know it's specified to be at least 64 bits wide).
I want to be able to refer to different parts of it, for example breaking it down into two uint32_ts, four uint16_ts or eight uint8_ts. Is there a standards compliant way to do it that doesn't rely on undefined behavior?
My approach is as follows:
class Buffer
{
uint64_t m_64BitBuffer;
public:
uint64_t & R64() { return m_64BitBuffer; }
uint32_t & R32(R32::Part part) { return *(reinterpret_cast<uint32_t*>(&m_64BitBuffer)+part); }
uint16_t & R16(R16::Part part) { return *(reinterpret_cast<uint16_t*>(&m_64BitBuffer)+part); }
uint8_t & R8(R8::Part part) { return *(reinterpret_cast<uint8_t*>(&m_64BitBuffer)+part); }
};
Where R32::Part, R16::Part and R8::Part are enums that define values between 0 and 1, 0 and 3 and 0 and 7 respectively.
I imagine this should be ok. There should be no issues with alignment, for example. I'd like to know if I'm breaking any rules, and if so, how to do this properly.
Type-punning through a union is allowed by some compilers, so you could simply have the following anonymous union member:
union {
uint64_t val;
struct { uint32_t as32[2]; };
struct { uint16_t as16[4]; };
struct { uint8_t as8[8]; };
} u;
Access to each part is as easy as reading from the appropriate member.

Using -1 to initialize an unsigned in { } initialization of struct or array

REALLY BRIEF
How do you create an unsigned constant that has all bits set?
...that you can use to initialize a field with { }s,
...that does not get a -Wnarrowing warning from GCC 4.7.2.
The following are not satisfactory:
struct U { unsigned ufield; };
struct Uc { unsigned char ufield; };
struct ULL { unsigned long long ufield; };
struct U32 { unsigned ufield; };
struct U64 { uint64_t ufield; }
typedef
//any of the above U Uc ULL U32 U64, we will arbitrarily choose:
U Ueg;
// somewhere far away
Ueg u = {-1}; // well defined by C standard, GCC 4.7.2 -Wnarrowing warning
Ueg u = {~0U}; // finit width constant, warnings in some places, silent non-all-1s-mask others
Ueg u = {~0ULL}; // ditto
Ueg u = {-1ULL}; // ditto
Basically, the user, the guy writing the {} initialization,
does not know the type of the ufield.
He only knows that it is an unsigned type, but not how wide.
Not exactly which unsigned type it is.
* Another Reason Why I want as simple and elegant a syntax as possible *
I might as well mention something else: the "user" here is not actually writing a C or C++ program.
He is editing a config file.
A program, a simple Perl or Python script, processes the config file, and generates C code.
This program is not very sophisticated, and at the moment passes through chunks of text that look like
Foo: {-1,2,3};
to generate
typedef
struct Some_Struct { unsigned a; unsigned b, unsigned c; }
Some_Struct = {-1,2,3}; // ditto
Basically, I want to be able to a nice user friendly syntax for a literal that says
"All of the bits in this unsigned value are set".
Without having to know how big of an unsigned.
And without the program that handles the config file getting too complicated.
Lest the potential answer-provider complain that this is a new constraint, not realistic, etc:
I have had exactly the same problem with templates.
I.e. with template types, where I want to write a literal that is "unsigned of any width, all 1s".
In a template I might be more willing to do some of the ugly, Ugly, UGLY syntax
that is obviously able to do this:
but I really wish there was a simple, elegant, syntax.
* The Real Question *
Q: is there any way to create a constant that is "all 1s set"
without triggering the GCC 4.7.2 warning?
BRIEF
I ran across a program that was using the literal constant -1 to initialize a field of a struct, e.g.
> cat ./-1u.cpp
#include <stdio.h>
struct U { unsigned ufield; } ustruct = { -1 };
int main(int argc, char** argv)
{
printf("ustruct.ufield = %08x\n",ustruct.ufield);
}
Although earlier versions of GCC accepted this without warning,
the fairly recent version GCC 4.7.2 provides a warning:
> /SOME-PATH/import/gcc/gcc-4.7.2.pkg/installdir/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:3:46: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
Note: this is only a warning. The result of converting -1 to unsigned is well defined in the C/C++ standards:
> ./a.out
ustruct.ufield = ffffffff
I dislike warnings, so I would like to silence this annoying warning. I prefer not to use #pragmas that apply to the entire file, since that may disable a warning for real bugs.
(By the way, you get this warnng only when initializing a field. Not when initializing a non-field
unsigned u = -1; // no cmpiler warning.
Doing
struct U { unsigned ufield; } ustruct = { ~0U };
silences the bug.
But it was pointed out that if the type of the field is not unsigned, but, instead, uint64_t,
then ~0U provides a different result than -1: 0x00000000FFFFFFFF rather than 0xFFFFFFFFFFFFFFFF.
(I.e. 32 bits of 1s, rather than 64 bits of 1s.)
The struct U and the initializaton code may live in completely different places,
and we would want to be able to increase the size of the field, a bitmask, without informing users.
And the intent is to get a "mask of all 1s" of whatever unsigned type is being used.
Similarly
struct U { unsigned ufield; } ustruct = { -1u };
silences the bug. (To my surprise - I did not know that -1 could be considered an unisgned.)
But is also a finite-width constant.
DETAIL
Here's a test program.
(By the way, all I am asking about is the use of the signed literal constant -1
to initialize an unsigned member. The other warnings are just tests.
You don;t need to explain to me that a 64 bit number doesn't fit in 32 bits.)
sh-3.2$ cat ./-1u.cpp
#include <stdio.h>
unsigned um1 = -1;
unsigned un0u = ~0u;
unsigned un0ull = ~0ull;
struct Foo {
unsigned um1;
unsigned un0u;
unsigned un0ull;
};
Foo foo = { -1, ~0u, ~0ull };
int main(int argc, char** argv)
{
printf("um1 = %08x\n",um1);
printf("un0u = %08x\n",un0u);
printf("un0ull = %08x\n",un0ull);
printf("foo.um1 = %08x\n",foo.um1);
printf("foo.un0u = %08x\n",foo.un0u);
printf("foo.un0ull = %08x\n",foo.un0ull);
}
sh-3.2$ /mips/proj/performance/import/gcc/gcc-4.7.2.pkg/installdir/bin/gcc -Wall ./-1u.cpp
./-1u.cpp:7:20: warning: large integer implicitly truncated to unsigned type [-Woverflow]
./-1u.cpp:15:28: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:28: warning: narrowing conversion of '18446744073709551615ull' from 'long long unsigned int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:28: warning: large integer implicitly truncated to unsigned type [-Woverflow]
sh-3.2$ /mips/proj/performance/import/gcc/gcc-4.7.2.pkg/installdir/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:7:20: warning: large integer implicitly truncated to unsigned type [-Woverflow]
./-1u.cpp:15:35: warning: narrowing conversion of '-1' from 'int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:35: warning: narrowing conversion of '18446744073709551615ull' from 'long long unsigned int' to 'unsigned int' inside { } is ill-formed in C++11 [-Wnarrowing]
./-1u.cpp:15:35: warning: large integer implicitly truncated to unsigned type [-Woverflow]
Doesn't occur in an earlier compiler:
sh-3.2$ /usr/bin/g++ -Wall ./-1u.cpp
./-1u.cpp:7: warning: large integer implicitly truncated to unsigned type
./-1u.cpp:15: warning: large integer implicitly truncated to unsigned type
/usr/bin/g++ --version
g++ (GCC) 4.1.2 20080704 (Red Hat 4.1.2-51)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
A slightly more user-friendly version of #Ali's answer:
#include <type_traits>
struct all_ones_type {
template <typename T,
typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
constexpr operator T () const
{ return static_cast<T>(-1); }
} const all_ones;
#include <iostream>
struct X {
unsigned short a;
unsigned long b;
unsigned long long c;
};
int main() {
X x = { all_ones, all_ones, all_ones };
std::cout << x.a << "\n"
<< x.b << "\n"
<< x.c << std::endl;
}
Depending on what you want to happen on an attempted conversion to signed type, you could change the enable_if to allow all integral types, or add another overload with a nice static_assert.
How about this? It only works for unsigned types but the question specifically says unsigned. (See rubenvb's comments below.)
#include <cinttypes>
#include <iomanip>
#include <iostream>
#include <limits>
#include <type_traits>
template <typename T>
T all_bits_one() {
static_assert(std::is_unsigned<T>::value, "the type must be unsigned");
return std::numeric_limits<T>::max();
}
struct Ui {
typedef unsigned int the_type;
the_type ufield;
};
struct ULL {
typedef unsigned long long the_type;
the_type ufield;
};
struct U64 {
typedef uint64_t the_type;
the_type ufield;
};
int main() {
using namespace std;
Ui ui = { all_bits_one< Ui::the_type>() };
ULL ull = { all_bits_one<ULL::the_type>() };
U64 u64 = { all_bits_one<U64::the_type>() };
cout << hex;
cout << "unsigned int: " << ui.ufield << endl;
cout << "unsigned long long: " << ull.ufield << endl;
cout << "unsigned int 64: " << u64.ufield << endl;
//all_bits_one<int>(); // causes compile-time error if uncommented
return 0;
}
The user doesn't have to know the exact type of the_type or the number of bits it is represented on.
There is some code duplication which could be removed but that would require a better understanding of your code and the problem you are dealing with.
I guess you simplified your code before posting. As it stands, your structs make no sense to me, a simple typedef would suffice.
Why not provide the mask along with the type?
C:
struct U { unsigned ufield; };
#define U_MASK (-1U)
// somewhere far away
U u = {U_MASK};
C++:
struct U { unsigned ufield; static constexpr unsigned MASK = -1; };
// somewhere far away
U u = {U::MASK};
All fancy template code aside, here's some fancy C++11 code:
struct Foo
{
unsigned a;
unsigned long b;
unsigned long long c;
};
Foo foo = { decltype(Foo::a)(-1), decltype(Foo::b)(-1), decltype(Foo::c)(-1) };
which is error-prone, but functional.
The best solution is still to use a (typed) enum (class) for this.
Another way
// C++03 and C++11
Ueg u = { (Ueg().ufield - 1) };
// C99 and C11 (works only inside of functions)
Ueg u = { (Ueg){0}.ufield - 1 };
Inspired by Ali, but using Template Argument Deduction.
T all_bits_one(T& dummy) { return ~(T()); }
unsigned long u = all_bits_one(u);
Maybe what you want by initializing an uint to -1 is that all bits are set to '1'?
In that case:
typedef uint MyUIntType;
MyUIntType mID = (MyUIntType)~0;
~ applies a "1's complement" to 0 which effectively flips all its bits.
The result will be the biggest value that your uint type can hold, which is useful in cases where 0 is a meaningful value and variables need to be initialized to "something else".

constexpr and endianness

A common question that comes up from time to time in the world of C++ programming is compile-time determination of endianness. Usually this is done with barely portable #ifdefs. But does the C++11 constexpr keyword along with template specialization offer us a better solution to this?
Would it be legal C++11 to do something like:
constexpr bool little_endian()
{
const static unsigned num = 0xAABBCCDD;
return reinterpret_cast<const unsigned char*> (&num)[0] == 0xDD;
}
And then specialize a template for both endian types:
template <bool LittleEndian>
struct Foo
{
// .... specialization for little endian
};
template <>
struct Foo<false>
{
// .... specialization for big endian
};
And then do:
Foo<little_endian()>::do_something();
New answer (C++20)
c++20 has introduced a new standard library header <bit>.
Among other things it provides a clean, portable way to check the endianness.
Since my old method relies on some questionable techniques, I suggest anyone who uses it to switch to the check provided by the standard library.
Here's an adapter which allows to use the new way of checking endianness without having to update the code that relies on the interface of my old class:
#include <bit>
class Endian
{
public:
Endian() = delete;
static constexpr bool little = std::endian::native == std::endian::little;
static constexpr bool big = std::endian::native == std::endian::big;
static constexpr bool middle = !little && !big;
};
Old answer
I was able to write this:
#include <cstdint>
class Endian
{
private:
static constexpr uint32_t uint32_ = 0x01020304;
static constexpr uint8_t magic_ = (const uint8_t&)uint32_;
public:
static constexpr bool little = magic_ == 0x04;
static constexpr bool middle = magic_ == 0x02;
static constexpr bool big = magic_ == 0x01;
static_assert(little || middle || big, "Cannot determine endianness!");
private:
Endian() = delete;
};
I've tested it with g++ and it compiles without warnings. It gives a correct result on x64.
If you have any big-endian or middle-endian proccesor, please, confirm that this works for you in a comment.
It is not possible to determine endianness at compile time using constexpr (before C++20). reinterpret_cast is explicitly forbidden by [expr.const]p2, as is iain's suggestion of reading from a non-active member of a union. Casting to a different reference type is also forbidden, as such a cast is interpreted as a reinterpret_cast.
Update:
This is now possible in C++20. One way (live):
#include <bit>
template<std::integral T>
constexpr bool is_little_endian() {
for (unsigned bit = 0; bit != sizeof(T) * CHAR_BIT; ++bit) {
unsigned char data[sizeof(T)] = {};
// In little-endian, bit i of the raw bytes ...
data[bit / CHAR_BIT] = 1 << (bit % CHAR_BIT);
// ... corresponds to bit i of the value.
if (std::bit_cast<T>(data) != T(1) << bit)
return false;
}
return true;
}
static_assert(is_little_endian<int>());
(Note that C++20 guarantees two's complement integers -- with an unspecified bit order -- so we just need to check that every bit of the data maps to the expected place in the integer.)
But if you have a C++20 standard library, you can also just ask it:
#include <type_traits>
constexpr bool is_little_endian = std::endian::native == std::endian::little;
Assuming N2116 is the wording that gets incorporated, then your example is ill-formed (notice that there is no concept of "legal/illegal" in C++). The proposed text for [decl.constexpr]/3 says
its function-body shall be a compound-statement of the form
{ return expression; }
where expression is a potential constant expression (5.19);
Your function violates the requirement in that it also declares a local variable.
Edit: This restriction could be overcome by moving num outside of the function. The function still wouldn't be well-formed, then, because expression needs to be a potential constant expression, which is defined as
An expression is a potential constant expression if it is a constant
expression when all occurrences of function parameters are replaced
by arbitrary constant expressions of the appropriate type.
IOW, reinterpret_cast<const unsigned char*> (&num)[0] == 0xDD would have to be a constant expression. However, it is not: &num would be a address constant-expression (5.19/4). Accessing the value of such a pointer is, however, not allowed for a constant expression:
The subscripting operator [] and the class member access . and
operators, the & and * unary operators, and pointer casts (except dynamic_casts, 5.2.7) can be used in the creation of an
address constant expression, but the value of an object shall not be accessed by the use of these operators.
Edit: The above text is from C++98. Apparently, C++0x is more permissive what it allows for constant expressions. The expression involves an lvalue-to-rvalue conversion of the array reference, which is banned from constant expressions unless
it is applied to an lvalue of effective integral type that refers
to a non-volatile const variable or static data member initialized
with constant expressions
It's not clear to me whether (&num)[0] "refers to" a const variable, or whether only a literal num "refers to" such a variable. If (&num)[0] refers to that variable, it is then unclear whether reinterpret_cast<const unsigned char*> (&num)[0] still "refers to" num.
There is std::endian in the upcoming C++20.
#include <bit>
constexpr bool little_endian() noexcept
{
return std::endian::native == std::endian::little;
}
My first post. Just wanted to share some code that I'm using.
//Some handy defines magic, thanks overflow
#define IS_LITTLE_ENDIAN ('ABCD'==0x41424344UL) //41 42 43 44 = 'ABCD' hex ASCII code
#define IS_BIG_ENDIAN ('ABCD'==0x44434241UL) //44 43 42 41 = 'DCBA' hex ASCII code
#define IS_UNKNOWN_ENDIAN (IS_LITTLE_ENDIAN == IS_BIG_ENDIAN)
//Next in code...
struct Quad
{
union
{
#if IS_LITTLE_ENDIAN
struct { std::uint8_t b0, b1, b2, b3; };
#elif IS_BIG_ENDIAN
struct { std::uint8_t b3, b2, b1, b0; };
#elif IS_UNKNOWN_ENDIAN
#error "Endianness not implemented!"
#endif
std::uint32_t dword;
};
};
Constexpr version:
namespace Endian
{
namespace Impl //Private
{
//41 42 43 44 = 'ABCD' hex ASCII code
static constexpr std::uint32_t LITTLE_{ 0x41424344u };
//44 43 42 41 = 'DCBA' hex ASCII code
static constexpr std::uint32_t BIG_{ 0x44434241u };
//Converts chars to uint32 on current platform
static constexpr std::uint32_t NATIVE_{ 'ABCD' };
}
//Public
enum class Type : size_t { UNKNOWN, LITTLE, BIG };
//Compare
static constexpr bool IS_LITTLE = Impl::NATIVE_ == Impl::LITTLE_;
static constexpr bool IS_BIG = Impl::NATIVE_ == Impl::BIG_;
static constexpr bool IS_UNKNOWN = IS_LITTLE == IS_BIG;
//Endian type on current platform
static constexpr Type NATIVE_TYPE = IS_LITTLE ? Type::LITTLE : IS_BIG ? Type::BIG : Type::UNKNOWN;
//Uncomment for test.
//static_assert(!IS_LITTLE, "This platform has little endian.");
//static_assert(!IS_BIG, "This platform has big endian.");
//static_assert(!IS_UNKNOWN, "Error: Unsupported endian!");
}
That is a very interesting question.
I am not Language Lawyer, but you might be able to replace the reinterpret_cast with a union.
const union {
int int_value;
char char_value[4];
} Endian = { 0xAABBCCDD };
constexpr bool little_endian()
{
return Endian[0] == 0xDD;
}
This may seem like cheating, but you can always include endian.h... BYTE_ORDER == BIG_ENDIAN is a valid constexpr...
Here is a simple C++11 compliant version, inspired by #no-name answer:
constexpr bool is_system_little_endian(int value = 1) {
return static_cast<const unsigned char&>(value) == 1;
}
Using a default value to crank everything on one line is to meet C++11 requirements on constexpr functions: they must only contain a single return statement.
The good thing with doing it (and testing it!) in a constexpr context is that it makes sure that there is no undefined behavior in the code.
On compiler explorer here.
If your goal is to insure that the compiler optimizes little_endian() into a constant true or false at compile-time, without any of its contents winding up in the executable or being executed at runtime, and only generating code from the "correct" one of your two Foo templates, I fear you're in for a disappointment.
I also am not a language lawyer, but it looks to me like constexpr is like inline or register: a keyword that alerts the compiler writer to the presence of a potential optimization. Then it's up to the compiler writer whether or not to take advantage of that. Language specs typically mandate behaviors, not optimizations.
Also, have you actually tried this on a variety of C++0x complaint compilers to see what happens? I would guess most of them would choke on your dual templates, since they won't be able to figure out which one to use if invoked with false.