To make it short, here is a minimal example:
struct C {
const int X = 2;
int y = 2;
};
void f(C* x) {
switch(x->y) {
case x->X: printf("%d", 42); break;
case 123: printf("foo");
}
}
int main()
{
C c;
f(&c);
return 0;
}
Why is the compiler complaining error: 'x' is not a constant expression and how to fix it?
Case labels inside switch accept only compile-time constant expressions. x->X is not a constant expression; hence it could not be used as a case label.
Replace the switch statement with an if to fix this problem:
if (x->y == x->X) {
printf("%d", 42);
} else if (x->y == 123) {
printf("foo");
}
In main, you declare an instance of C and pass it to f. According to the definition of f, it does not guarantee that c does not get changed - and main has no way to verify it.
I think f needs to be f(C * const x);
The given code (modulo formatting)
struct C
{
int const x = 2;
int y = 2;
};
… means this:
struct C
{
int const x;
int y;
C(): x( 2 ), y( 2 ) {}
};
… i.e. the members are initialized by each constructor.
You can even override that initialization in a user defined constructor:
struct S
{
int const x = 2;
S(): x( 3 ) {}
};
Here in every instance x will be 3.
And so x isn't a compile time constant. It's very much a run time thing. And as such it can't be used as a case label in a switch, because a case label must be a value known at compile time. In turn because the switch construct is designed to be efficiently implemented as simple array indexing (a computed jump) when the value range permits that.
One simple fix is to define the relevant value as a compile time constant. Either as a static or enum value inside the class. Or outside the class.
Another possible fix is to use an if-else ladder instead of a switch.
Case accepts Constant Expression,like 2 or 'a'.And Const just define an unchanging variant.
Related
Sometimes for algebraic types it is convenient to have a constructor that takes a literal value 0 to denote the neutral element, or 1 to denote the multiplicative identity element, even if the underlying type is not an integer.
The problem is that it is not obvious how to convince the compiler only to accept, 0 or 1 without accepting any other integer.
Is there a way to do this in C++14 or beyond, for example combining literals, constexpr or static_assert?
Let me illustrate with a free function (although the idea is to use the technique for a constructor that take a single argument. Contructors cannot take template parameters either).
A function that accepts zero only could be written in this way:
constexpr void f_zero(int zero){assert(zero==0); ...}
The problem is that, this could only fail at runtime. I could write f_zero(2) or even f_zero(2.2) and the program will still compile.
The second case is easy to remove, by using enable_if for example
template<class Int, typename = std::enable_if_t<std::is_same<Int, int>{}> >
constexpr void g_zero(Int zero){assert(zero==0);}
This still has the problem that I can pass any integer (and it only fails in debug mode).
In C++ pre 11 one had the ability to do this trick to only accept a literal zero.
struct zero_tag_{};
using zero_t = zero_tag_***;
constexpr void h_zero(zero_t zero){assert(zero==nullptr);}
This actually allowed one to be 99% there, except for very ugly error messages.
Because, basically (modulo Maquevelian use), the only argument accepted would be h_zero(0).
This is situation of affairs is illustrated here https://godbolt.org/z/wSD9ri .
I saw this technique being used in the Boost.Units library.
1) Can one do better now using new features of C++?
The reason I ask is because with the literal 1 the above technique fails completely.
2) Is there an equivalent trick that can be applied to the literal 1 case? (ideally as a separate function).
I could imagine that one can invent a non-standard long long literal _c that creates an instance of std::integral_constant<int, 0> or std::integral_constant<int, 1> and then make the function take these types. However the resulting syntax will be worst for the 0 case. Perhaps there is something simpler.
f(0_c);
f(1_c);
EDIT: I should have mentioned that since f(0) and f(1) are potentially completely separate functions then ideally they should call different functions (or overloads).
In C++20 you can use the consteval keyword to force compile time evaluation. With that you could create a struct, which has a consteval constructor and use that as an argument to a function. Like this:
struct S
{
private:
int x;
public:
S() = delete;
consteval S(int _x)
: x(_x)
{
if (x != 0 && x != 1)
{
// this will trigger a compile error,
// because the allocation is never deleted
// static_assert(_x == 0 || _x == 1); didn't work...
new int{0};
}
}
int get_x() const noexcept
{
return x;
}
};
void func(S s)
{
// use s.get_x() to decide control flow
}
int main()
{
func(0); // this works
func(1); // this also works
func(2); // this is a compile error
}
Here's a godbolt example as well.
Edit:
Apperently clang 10 does not give an error as seen here, but clang (trunk) on godbolt does.
You can get this by passing the 0 or 1 as a template argument like so:
template <int value, typename = std::enable_if_t<value == 0 | value == 1>>
void f() {
// Do something with value
}
The function would then be called like: f<0>(). I don't believe the same thing can be done for constructors (because you can't explicitly set template parameters for constructors), but you could make the constructor(s) private and have static wrapper functions which can be given template parameters perform the check:
class A {
private:
A(int value) { ... }
public:
template <int value, typename = std::enable_if_t<value == 0 || value == 1>>
static A make_A() {
return A(value);
}
};
Objects of type A would be created with A::make_A<0>().
Well... you have tagged C++17, so you can use if constexpr.
So you can define a literal type when 0_x is a std::integral_constant<int, 0> value, when 1_x is a std::integral_constant<int, 1> and when 2_x (and other values) gives a compilation error.
By example
template <char ... Chs>
auto operator "" _x()
{
using t0 = std::integer_sequence<char, '0'>;
using t1 = std::integer_sequence<char, '1'>;
using tx = std::integer_sequence<char, Chs...>;
if constexpr ( std::is_same_v<t0, tx> )
return std::integral_constant<int, 0>{};
else if constexpr ( std::is_same_v<t1, tx> )
return std::integral_constant<int, 1>{};
}
int main ()
{
auto x0 = 0_x;
auto x1 = 1_x;
//auto x2 = 2_x; // compilation error
static_assert( std::is_same_v<decltype(x0),
std::integral_constant<int, 0>> );
static_assert( std::is_same_v<decltype(x1),
std::integral_constant<int, 1>> );
}
Now your f() function can be
template <int X, std::enable_if_t<(X == 0) || (X == 1), bool> = true>
void f (std::integral_constant<int, X> const &)
{
// do something with X
}
and you can call it as follows
f(0_x);
f(1_x);
For the case of Ada, you can define a subtype, a new type, or a derived type that is constrained only for the values of Integer 0 and 1.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
procedure two_value is
-- You can use any one of the following 3 declarations. Just comment out other two.
--subtype zero_or_one is Integer range 0 .. 1; -- subtype of Integer.
--type zero_or_one is range 0 .. 1; -- new type.
type zero_or_one is new Integer range 0 .. 1; -- derived type from Integer.
function get_val (val_1 : in zero_or_one) return Integer;
function get_val (val_1 : in zero_or_one) return Integer is
begin
if (val_1 = 0) then
return 0;
else
return 1;
end if;
end get_val;
begin
Put_Line("Demonstrate the use of only two values");
Put_Line(Integer'Image(get_val(0)));
Put_Line(Integer'Image(get_val(1)));
Put_Line(Integer'Image(get_val(2)));
end two_value;
upon compiling you get the following warning message, although compiles successfully :
>gnatmake two_value.adb
gcc -c two_value.adb
two_value.adb:29:40: warning: value not in range of type "zero_or_one" defined at line 8
two_value.adb:29:40: warning: "Constraint_Error" will be raised at run time
gnatbind -x two_value.ali
gnatlink two_value.ali
And executing it gives the runtime error as specified by the compiler
>two_value.exe
Demonstrate the use of only two values
0
1
raised CONSTRAINT_ERROR : two_value.adb:29 range check failed
So, basically you can constrain the values by defining the new types, derived types or subtypes, you don't need to include the code to check the range, but based on your data type the compiler will automatically warn you.
This isn't a modern solution, but adding on to Zach Peltzer's solution, you can keep your syntax if you use macros...
template <int value, typename = std::enable_if_t<value == 0 | value == 1>>
constexpr int f_impl() {
// Do something with value
return 1;
}
#define f(x) f_impl<x>()
int main() {
f(0); //ok
f(1); //ok
f(2); //compile time error
}
Though, with the constructor problem you could just make the class templated instead of trying to have a templated constructor
template<int value, typename = std::enable_if_t<value == 0 | value == 1>>
class A {
public:
A() {
//do stuff
}
};
int main() {
A<0> a0;
auto a1 = A<1>();
// auto a2 = A<2>(); //fails!
}
The best solution to accept literal 0 that I've found to date is to use std::nullptr_t as the function's input:
struct math_object
{
real x,y,z;
math_object(std::nullptr_t) : x(0), y(0), z(0) {}
};
This has conversion advantages over some of the other solutions. For example, it allows syntax such as.. void MyFunc(const math_object &obj=0); I've been using this for years, and haven't found any trouble. However, I do not have a similar solution for literal 1. For that, I created a construct::id structure that has a global IDENTITY variable.
There's a basic problem. How can you do that in the compiler to be done for a parameter, and at the same time be efficient? Well, what do you need exactly?
That is included in strong typed languages like Pascal, or Ada. The enumerated types have only a couple of values, and the types are normally checked at development, but otherwise, the checks are eliminated by some compiler option at runtime, because just everything goes well.
A function interface is a contract. It is a contract between a seller (the writer of the function) and a buyer (the user of that function). There's even an arbiter, which is the programming language, that can act upon if someone tries to cheat the contract. But at the end, the program is being run in a machine that's open to make arbitraryness like modifying the set of enumerated values and put in the place a completely (and not permitted value).
The problem comes also with separate compilation. Separate compilation has its drawbacks, as it must face a compilation, without having to recheck and retest all previous compilations you have made. Once a compilation is finished, everything you have put in the code is there. If you want the code to be efficient, then the tests are superfluous, because caller and implementer both cope with the contract, but if you want to catch a lyer, then you have to include the test code. And then, it is better to do once for all cases, or is it better to let the programmer decide when and when not we want to catch a lyer?
The problem with C (and by legacy with C++) is that they were inspired by very good programmers, that didn't mistakes, and that have to run their software in big and slow machines. They decided to make both languages (the second was for interoperability purposes) weak typed... and so they are. Have you tried to program in Ada? or Modula-2? You'll see that, over the time, the strong typing thing is more academic than otherwise, and finally what you want, as a professional, is to have the freedom to say: now I want to be safe (and include test code), and now I know what I'm doing (and please be most efficient as you can)
Conclusion
The conclussion is that you are free to select the language, to select the compiler, and to relax the rules. The compilers have the possibility to allow you that. And you have to cope with it, or invent (this is something that todays happens almost each week) your own programming language.
This is the answer to my question, based on #IlCapitano answer for a wrapper class.
This wrapper class can be made private an used only on the construction.
class Matrix {
struct ZeroOROne {
/*implicit*/ consteval ZeroOROne(int n) : val_{n} {
if (n != 0 and n != 1) {throw;} // throw can produce an error at compile time
}
int val_;
};
public:
constexpr Matrix(ZeroOROne _0_or_1) {
if(_0_or_1.val_ == 0) { // this cannot be if constexpr, but that is ok
a00 = a01 = a10 = a11 = 0.0;
new int{0}; // allocation could is ok here
} else {
a00 = a11 = 1.0;
a10 = a01 = 0.0;
new int{0}; // allocation could is ok here
}
}
double a00; double a01;
double a10; double a11;
};
In this way, only Matrix A(0) or Matrix A(1) are allowed.
(Although it works with constant variables as well, but that is ok.)
int main() {
// ZeroOROne(0);
// ZeroOROne(1);
// ZeroOROne(2); // compilation error
Matrix A(0);
Matrix B(1);
// Matrix C(2); // compilation error
int const d = 0; // this works because the compiler can "see" the 0.
Matrix D(d);
constexpr int e = 0;
Matrix E(e);
// int f = 0;
// Matrix F(f); // compile error
return B.a00;
}
Here it is shown that the "runtime" if in the constructor is not a problem and can be elided by the compiler: https://godbolt.org/z/hd6TWY6qW
The solution needs C++20 and it works in recent version of GCC and clang.
So I wrote this code and was kind of surprised when it compiled (I am using gcc version 5.1.0):
struct Mine
{
const int* ptr;
Mine(const int x)
: ptr([=]()
{
static const int n = x;
return &n;
}()
){}
};
Mine first = 12;
Mine second = 13;
The reason I am surprised is that each declaration of Mine creates a new "global" variable.
So here is the question:
Am I supposed to be allowed to do this?
There is only one n and all ptr's are equal.
So, no.
I am programming with C++11 and was wondering if there is a way to generate some code during execution.
For example instead of writing:
void b(int i){i+1}
void c(int i){i-1}
if(true) b()
else{ c() }
would there be a more straightforward way to say if true, then replace all + with - ?
Thank you and sorry if this question is stupid..
C++ has no native facilities for runtime code generation. You could of course invoke a C++ compiler from your program, then dynamically load the resulting binary, and call code from it, but I doubt this is the best solution to your problem.
If you are worried about repeatedly checking the condition, you shouldn't be. Modern CPUs will likely deal with this very well, even in a tight loop, due to branch prediction.
Last, if you really want to more dynamically alter the code path you take, you could use function pointers and/or polymorphism and/or lambdas.
An example with functions
typedef void (pFun*)(int); // pointer to function taking int, returning void
void b(int i){i+1}
void c(int i){i-1}
...
pFun d = cond ? b : c; // based on condition, select function b or c
...
pFun(i); // calls either b or c, effectively selecting + or -
An example with polymorphism
class Operator
{
public:
Operator() {}
virtual ~Operator() {}
virtual void doIt(int i) = 0;
};
class Add : public Operator
{
public:
virtual void doIt(int i) { i+1; }
};
class Sub : public Operator
{
public:
virtual void doIt(int i) { i-1; }
};
...
Operator *pOp = cond ? new Add() : new Sub();
...
pOp->doIt(i);
...
delete pOp;
Here, I have defined a base class with the doIt pure virtual function. The two child classes override the doIt() function to do different things. pOp will then point at either an Add or a Sub instance depending on cond, so when pOp->doIt() is called, the appropriate implementation of your operator is used. Under the covers, this does essentially what I outlined in the above example with function pointers, so choosing one over the other is largely a matter of style and/or other design constrains. They should both perform just as well.
An example with lambdas
This is basically the same as the first example using function pointers, but done in a more C++11 way using lambdas (and it is more concise).
auto d = cond ? [](int i) { i+1; }
: [](int i) { i-1; };
...
d(i);
Alternatively, you may prefer to have the condition inside the body of the lambda, for example
auto d = [&](int i) { cond ? i+1 : i-1; }
...
d(i);
C++ does not have runtime code generation since it's a compiled language.
In this case, you could put the sign into a variable (to be used with multiple variables.)
E.g.
int sign = (true ? 1 : -1);
result2 += sign;
result1 += sign;
Not necessarily a solution for your problem, but you could use
a template, instantiated on one of the operators in <functional>:
template <typename Op>
int
func( int i )
{
return Op()( i, 1 );
}
In your calling function, you would then do something like:
int (*f)( int i ) = condition ? &func<std::plus> : &func<std::minus>;
// ...
i = f( i );
It's possible to use lambdas, which may be preferable, but you can't use
the conditional operator in this case. (Every lambda has a unique type,
and the second and third operatands of the conditional operator must
have the same type.) So it becomes a bit more verbose:
int (*f)( int i );
if ( condition ) {
f = []( int i ) { return i + 1; }
} else {
f = []( int i ) { return i - 1; }
}
This will only work if there is no capture in the lambdas; when there is
no capture, the lambda not only generates an instance of a class with
a unique type, but also a function. Although not being able to use the
conditional operator makes this more verbose than necessary, it is still
probably simpler than having to define a function outside of the class,
unless that function can be implemented as a template, as in my first
example. (I'm assuming that your actual case may be significantly more
complicated than the example you've posted.)
EDIT:
Re lambdas, I tried:
auto f = c ? []( int i ) { return i + 1; } : []( int i ) { return i - 1; };
just out of curiosity. MSC++ gave me the expected error
message:
no conversion from 'someFunc::<lambda_21edbc86aa2c32f897f801ab50700d74>' to 'someFunc::<lambda_0dff34d4a518b95e95f7980e6ff211c5>'
but g++ compiled it without complaining, typeid(f) gave "PFiiI",
which I think is a pointer to a function. In this case, I'm pretty sure
that MSC++ is right: the standard says that each of the lambdas has
a unique type, and that each has a conversion operator to (in this
case) an int (*)( int ) (so both can be converted to the same
type—this is why the version with the if works). But the
specification of the conditional operator requires that either the
second operand can be converted to the type of the third, or vice versa,
but the results must be the type of one of the operands; it cannot be
a third type to which both are converted.
Suppose I have a class:
class test {
public:
void print();
private:
int x;
};
void test::print()
{
cout<< this->x;
}
and I have these variable definitions:
test object1;
test object2;
When I call object1.print() this happens to store address of object1 and so I get x from object1 printed and when I call object2.print() this happens to store address of object2 and I get x from object2 printed. How does it happen?
Each non-static member function has an implicit hidden "current object" parameter that is exposed to you as this pointer.
So you can think that for
test::print();
there's some
test_print( test* this );
global function and so when you write
objectX.print();
in your code the compiler inserts a call to
test_print(&objectX);
and this way the member function knows the address of "the current" object.
You can think of the this pointer being an implicit argument to the functions. Imagine a little class like
class C {
public:
C( int x ) : m_x( x ) { }
void increment( int value ) {
m_x += value; // same as 'this->m_x += value'
}
int multiply( int times ) const {
return m_x * times; // same as 'return this->m_x * times;'
}
private:
int m_x;
};
which allows you to write code like
C two( 2 );
two.increment( 2 );
int result = two.multiply( 3 );
Now, what's actually happening is that the member functions increment and multiply are called with an extra pointer argument, pointing to the object on which the function is invoked. This pointer is known as this inside the method. The type of the this pointer is different, depending on whether the method is const (as multiply is) or not (as is the case with increment).
You can do something like it yourself as well, consider:
class C {
public:
C( int x ) : m_x( x ) { }
void increment( C * const that, int value ) {
that->m_x += value;
}
int multiply( C const * const that, int times ) const {
return that->m_x * times;
}
private:
int m_x;
};
you could write code like
C two( 2 );
two.increment( &two, 2 );
int result = two.multiply( &two, 3 );
Notice that the type of the this pointer is C const * const for the multiply function, so both the pointer itself is const but also the object being pointed to! This is why you cannot change member variables inside a const method - the this pointer has a type which forbids it. This could be resolved using the mutable keyword (I don't want to get side-tracked too far, so I'll rather not explain how that works) but even using a const_cast:
int C::multiply( int times ) const {
C * const that = const_cast<C * const>( this );
that->m_x = 0; // evil! Can modify member variable because const'ness was casted away
// ..
}
I'm mentioning this since it demonstrates that this isn't as special a pointer as it may seem, and this particular hack is often a better solution than making a member variable mutable since this hack is local to one function whereas mutable makes the variable mutable for all const methods of the class.
The way to think about it is that this is simply a pointer to the memory for whichever object you're currently working with. So if you do obj1.print(), then this = &obj1;. If you do obj2.print(), then this = &obj2;.
this has different values for different objects
Each instance of class test gets it's own copy of member variable x. Since x is unique for each instance, the value can be anything you want it to be.
The variable this, refers to the instance to which it is associated. You don't have to use the variable 'this'. You could just write:
void test::print()
{
cout << x;
}
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Is there some ninja trick to make a variable constant after its declaration?
Sometimes in C or C++ we have a variable that might be const, but we have to take some lines of code to initialize it.
Is there a way to tell the compiler that, from some point in a function, some already constructed variable has to be considered as const, until its scope ends?
Something like:
int c = 0;
// the value of c is initialized here
switch(someVar) {
case foo: c = 3; break;
case bar: c = 4; break;
default : c = 42; // what else?
}
// now c is constant
ASSUME_CONST_FROM_NOW(c) // some #pragma maybe?
I know that I could initialize the variable in a dedicated function. This is not really what I am asking for.
Another example:
int c = 0; int d = 0;
{ /*some block of code that initializes both c and d jointly*/ }
ASSUME_CONST_FROM_NOW(c, d)
There is no function that can return two values at a time without creating structures or classes.
But such a trick could be useful in order to make old, crappy code more easily understandable with not much refactoring.
Yes.
Put the initialization in a function.
int getInitCValue(int const& someVar)
{
// the value of c is initialized here
switch(someVar)
{
case foo: return 3;
case bar: return 4;
default : return 42; // what else?
}
}
int const c = getInitCValue(someVar);
Edit: To answer the modified question.
You want to initialize two values:
std::pair<int,int> const value = initalizePairOfValues(someValue);
int const& c = value.first;
int const& d = value.second;
Edit 2: Go with Péter Török deleted solution (Peter if you un-delete I will remove this).
struct ConstValues
{
ConstValues()
{
switch(....)
// Initialize C/D
}
int const& getC() const {return c;}
int const& getD() const {return d;}
private:
int c;
int d;
};
In C++0x, you can do something like this:
int const c = []() -> int {
int r;
switch(42) {
case 3:
r = 1; break;
case 4:
r = 2; break;
default:
r = 23;
};
return r;
}();
If you are willing to provide some {} around the code that is to see the variable const, yes, at least something similar. Put something like the following in a macro:
#define CONSTIFY(T, NAME) \
for (bool p00 = true; p00; p00=false) \
for (T p000 = NAME; p00; p00=false) \
for (T const NAME = p000; p00; p00=false)
this should work in C99 as well as in C++. Technically, this doesn't make your original variable const but creates a new variable with the same contents for the depending scope.
And beware that in some cases (break or continue) this might change the control flow. But as long as you wrap this around something which is basically a whole function body, this should work.