"F (5)" and "int x; F (x)" to call different functions?

I would like to write two different functions for processing a constant value and a variable of a given type (i.e. int ).

Here is a test case example:

 int main(void) { int x=12; F(5); // this should print "constant" F(x); // this should print "variable" } 

I thought this was enough to determine:

 void F(int v) { cout << "constant\n"; } void F(int& v) { cout << "variable\n"; } 

This assumes that the compiler will select int& for variables as "more specialized" and int for constants as the only choice). However, G++ is the result:

 test.cc: In function 'int main()': test.cc:13: error: call of overloaded 'F(int&)' is ambiguous // for line: F(x); test.cc:4: note: candidates are: void F(int) test.cc:5: note: void F(int&) 

G++ selects F(int) for constants, but does not know which function to choose for variables. Does anyone know why this is happening?

Background . I am experimenting with prolog-like unification methods in C ++. The ability to know the difference between constants and variables will help me choose the desired unified behavior (assignment or comparison) in cases such as functor(x,5) <=> functor(3,5) .

+2
c ++
source share
1 answer

If you want to distinguish between a compilation time constant and a time constant other than compilation, then you have no chance. It's impossible.

But if you want to distinguish between a variable variable and a constant variable (and everything else is just literals), then you can overload the function with a reference to const-reference and non-const. For this scenario, the C ++ standard introduces additional rules that make this case ambiguous, but not ambiguous.

 void f(int const&); // #1 void f(int&); // #2 

The following decisions are made in this matter.

 int x = 0; int const y = x; int const z = 1; f(1); // #1 f(x); // #2 f(y); // #1 f(z); // #1 

Note that it cannot distinguish between y and z, although z is a compile-time constant (called an integral constant expression or ICE), but y is not.

What you can do is just take compile time values. Overload the function so that it is a template and the other is not

 template<int N> void f(); // #1 void f(int n); // #2 

Then he behaves like this:

 int x = 0; int const y = x; int const z = 1; f<1>(); // #1 f(1); // #2 f<y>(); // error, y not an ICE f<z>(); // #1 f(x); // #2 
+16
source share

All Articles