Consider a class like:
struct mystruct
{
constexpr operator char() {return x;}
signed char x;
};
and an operation like:
mystruct m;
m.x = /* something at runtime */
int i = 3 * m + 45ULL * m;
Are compilers able to skip the temporary conversion to char and convert directly m to the required type in the 3 * m + 45ULL * m expression?
Seems like GCC version 5.3.0 is able to optimize the call to cast function, while Clang 3.7 is not as smart.
For this piece of code:
struct mystruct
{
constexpr operator char() const {return x;}
signed char x;
} m;
void func(const int num) {
m.x = num*2;
int i = 3 * m + 45ULL * m;
}
you can check compiled assembly and compare them:
Clang with cast vs Clang with direct reference to field
Gcc with cast vs Gcc with direct reference to field
Though in a slightly different situation Clang does manage to optimize the call to cast function.
Related
I'am learning C++ so I'am currently reading the book "C++ Primer".
I was reading some examples about the "constexpr variables" and I just want to try a basic code that I just wrote but it doesn't compile I don't know why.
This is the code :
#include <iostream>
using namespace std;
int j = 8;
const int *p = &j;
int main()
{
constexpr int i = *p; // *p should be 8.
return 0;
}
The compiler says : "the value of 'p' is not usable in a constant expression"
If I replace the "constexpr" by "const" no problem at all but I think that because the value of *p should be known at compile time there shouldn't be any problems.
I don't know where I made a mistake.
(Please be tolerant my first language is French)
The reason this does not compile is because J is not const or constexpr.
Also note P is "just" const pointer.
This means *P can not be changed, but P itself is free to be changed.
Here is an example:
int f(){
int a = 5;
int b = 6;
int *p = nullptr;
p = &a; // *p -> a -> 5
p = &b; // *p -> a -> 6
return *p;
}
I want to clarify something for const vs constexpr:
const is not constexpr, but some for some primitive types there is no difference:
This compiles:
const int j = 8;
constexpr const int *p = &j;
int main(){
constexpr int i = *p;
return i;
}
Also this compiles:
constexpr int j = 8;
constexpr const int *p = &j;
int main(){
constexpr int i = *p;
return i;
}
However this does not compiles:
const int j = 8;
const int *const p = &j;
int main(){
constexpr int i = *p;
return i;
}
It seems the fundamental misunderstanding you have is the difference between an object being const vs constexpr. A variable being const means that it's logically const, i.e. the value cannot be changed once it's initialized. That does not mean that the value is known at compile time, which is what constexpr signifies.
For some type T
T t = {}; // not const, not constexpr
const T t = {}; // const, but not constexpr
constexpr T t = {}; // constexpr, also implies const
All good so far, but there's an additional wrinkle: a variable of integral or enumeration type that is const and is assigned a constant expression, is also constexpr. There are good reasons for this difference, but what that means is:
const int i = 42; // i is int, and const, so it's also constexpr !!
And of course, if you want to use an expression as a constant expression, it must have been declared as a constexpr variable or function.
Which one, if not both, is breaking spec? Tried with MSVC on both MSVC 2013 and MSVC Nov 2013 CTP, GCC was MinGW x64 4.9.1 with -std=c++11.
template<typename ret_type>
class memoizer
{
using func_type = ret_type(*)(const int);
const func_type func;
std::map<int, ret_type> cache;
public:
memoizer(func_type func) : func(func)
{
}
ret_type operator [](const int n)
{
const auto it = cache.find(n);
if(it != cache.end())
return it->second;
return cache[n] = func(n);
}
};
//works in GCC but not MSVC
//error C2065: 'fib' : undeclared identifier
memoizer<int64_t> fib([](const int n)
{
return n < 2 ? n : fib[n - 1] + fib[n - 2];
});
//works in MSVC but not GCC
//error: conversion from '<lambda(int)>' to non-scalar type 'memoizer<long long int>' requested
memoizer<int64_t> fib = [](const int n)
{
return n < 2 ? n : fib[n - 1] + fib[n - 2];
};
This seems to stem from the way they're handling lambda types differently, and when they consider a variable to be defined.
GCC is right.
For your first form:
A variable is considered declared at the end of its declarator, which is before its initialiser. This is why the this form is valid. The famous example is int i = i;, which is syntactically valid and initialises i with its own (indeterminate) value.
For your second form:
Your initialisation with = fails because you have two user-defined conversions. (The lambda type's conversion operator is considered user-defined.) It is analogous to
struct A { };
struct B { B(A) { } };
struct C { C(B) { } };
A a;
C c1(a); // okay
C c2 = a; // error
This question already has answers here:
How to ensure constexpr function never called at runtime?
(5 answers)
Closed 1 year ago.
In C++11 we get constexpr:
constexpr int foo (int x) {
return x + 1;
}
Is it possible to make invocations of foo with a dynamic value of x a compile time error? That is, I want to create a foo such that one can only pass in constexpr arguments.
Replace it with a metafunction:
template <int x> struct foo { static constexpr int value = x + 1; };
Usage:
foo<12>::value
Unfortunately, there is no way guarantee that a constexpr function, even the most trivial one, will be evaluated by the compiler unless absolutely necessary. That is, unless it appears in a place where its value is required at compile time, e.g. in a template. In order to enforce the compiler to do the evaluation during compilation, you can do the following:
constexpr int foo_implementation (int x) {
return x + 1;
}
#define foo(x) std::integral_constant<int, foo_implementation(x)>::value
and then use foo in your code as usual
int f = foo(123);
The nice thing about this approach is that it guarantees compile-time evaluation, and you'll get a compilation error if you pass a run-time variable to foo:
int a = 2;
int f = foo(a); /* Error: invalid template argument for 'std::integral_constant',
expected compile-time constant expression */
The not so nice thing is that it requires a macro, but this seems currently inevitable if you want both guaranteed compile-time evaluation and pretty code. (I'd love to be proven wrong though!)
Yes, it can now be done in purely idiomatic C++, since C++20 added support for this kind of problem. You annotate a function with consteval and can be sure that it's being evaluated during compile time. https://en.cppreference.com/w/cpp/language/consteval
consteval int foo( int x ) {
return x + 1;
}
int main( int argc, char *argv[] )
{
return foo( argc ); // This will not compile
return foo( 1 ); // This works
}
Also see this godbolt.org demo in the 3 most relevant compilers.
I would use static_assert as shown in this example
#include<iostream>
constexpr int foo(int x) {
return x+1;
}
int main() {
// Works since its static
std::cout << foo(2) << std::endl;
static_assert(foo(2) || foo(2) == 0, "Not Static");
// Throws an compile error
int in = 3;
std::cout << foo(in) << std::endl;
static_assert(foo(in) || foo(in) == 0, "Not Static");
}
For more infos: http://en.cppreference.com/w/cpp/language/static_assert
If I declare an anonymous union in a function…
void f(int in) {
union { int i; float f; };
// …
}
…does syntax exist to initialize it (other than assigning to i or f in another statement? A quick look at the spec suggests no. The obvious ones don’t compile:
// Nope:
union { int i = in; float f; };
union { int i; float f; } = in;
union { int i; float f; } = {in};
union { int i; float f; }{in};
union { int i; float f; }(in);
This works (at least in gcc 4.7.2):
union { int i; float f; } x = {1};
Notice that the type (i.e. the union) is anonymous but its instanciation is called x.
What you were trying to achieve (e.g. union { int i; float f; }{in};) doesn't compile but suppose it did. Then you would be creating an unnamed object (a temporary) of an unnamed type. The temporary would be destroyed at the end of the expression and, therefore, this statement would have no effect. So what's the point?
See update below -- I'm not sure whether this is a language restriction or a compiler limitation.
In the absence of designated initializers (added to C in 1999, so far nonexistent in C++ as far as I know), an initializer for a union can only specify a value for the first named member:
union { int i; float f; } obj = { 42 }; // sets obj.i to 42
C, as of the 1999 standard, provides designated initializers that let you initialize any named member you like:
union { int i; float f; } obj = { .f = 1.25 };
Since C++ doesn't have this feature, you're pretty much out of luck unless you happen to want to initialize the first named member.
Of course you can use an assignment:
union { int i; float f; } obj;
obj.f = 1.25;
which I suggest is a perfectly good workaround. You can do what you want; you just can't do it with the syntax you want.
Giving the union type a name wouldn't be particularly helpful in this case, unless you make it visible in a wider scope and write a function that returns a value of the type:
union u { int i; float f; };
u init_f(float f) { u result; result.f = f; return result; }
// later
u obj = init_f(1.25);
UPDATE :
I wasn't aware of the existence of anonymous union in C++ when I wrote the above. C11 permits anonymous unions and structs, but only as members of an enclosing union or struct. C++11 permits an anonymous union object to be defined, as in this example from the standard:
void f() {
union { int a; const char* p; };
a = 1;
p = "Jennifer";
}
g++ 4.7.2 seems not to permit anonymous union objects to be initialized. For example, this:
int main() {
union {
int i;
float f;
} = { 42 };
}
results in the following errors with g++ -std=c++11:
c.cpp: In function ‘int main()’:
c.cpp:5:5: error: expected ‘;’ after union definition
c.cpp:5:7: error: expected primary-expression before ‘=’ token
I don't see anything in section 9.5 of the C++11 standard that forbids initializers for anonymous unions, which makes me think that this is a limitation of g++, presumably to be corrected in a future release.
Whether this limitation is imposed by the language or by g++, you can work around it either by giving the union a name:
union { int i; float f; } obj = { 42 };
(but then you have to refer to obj.i and obj.f rather than just i and f), or by using an assignment rather than an initializer:
union { int i; float f; };
i = 42;
(I'll clean up this answer once we resolve whether this restriction is imposed by the language or by the compiler.)
Why is the conversion constructor not called implicitly for i2?
class NumString
{
public:
NumString(const char* s)
{
}
int operator*( int i)
{
return 42;
}
};
int main(void)
{
int i1 = (NumString) "string" * 2; //OK
int i2 = "string" * 2; //ERROR
}
Because the compiler doesn't invoke user-defined conversions where there aren't any user-defined types involved.
The expression "string" * 2 involves just a const char * and an int, why should the compiler consider NumString in any way?
If it worked like you expect, how would the complier be expected to choose the correct conversion if more than one class had a suitable converting constructor?