danglingpointer
danglingpointer

Reputation: 712

Overloading function calls for compile-time constants

I'm interested to know whether one can distinguish between function calls using arguments provided by compile-time constants and those without?

For example:

int a = 2;
foo( a )  // #1: Compute at run-time
foo( 3 )  // #2: Compute at compile-time

Is there any way to provide overloads that distinguish between these two cases? Or more generally, how do I detect the use of a literal type?

I've looked into constexpr, but a function parameter cannot be constexpr. It would be neat to have the same calling syntax, but be able to generate different code based on the parameters being literal types or not.

Upvotes: 4

Views: 717

Answers (3)

newbie
newbie

Reputation: 154

I think the above answers somehow miss the point that the question was trying to make.

Is there any way to provide overloads that distinguish between these two cases? Or more generally, how do I detect the use of a literal type?

this is what a 'rvalue reference' is for. literal type is a rvalue.

It would be neat to have the same calling syntax, but be able to generate different code based on the parameters being literal types or not.

you can simply overload your foo() function as:

void foo(int&& a);

So when you call the function with a literal, e.g. foo(3), the compiler knows you need the above overload, as 3 is a rvalue. If you call the function as foo(a), the compiler will pick up your original version foo(const int& a); as int a=2; is a lvalue.

And this gives you the same calling syntax.

Upvotes: 2

PaulG
PaulG

Reputation: 678

In the general case you couldn't get foo(3) evaluated at compile time. What if foo(x) was defined as add x days to the current date - and you first run the program next Tuesday? If it really is a constant then use a symbolic constant. If it is a simple function you could try a define (which will be replaced at compile time with the implementation -but it still will be evaluated at runtime)

e.g.

#define MIN(x,y) ((x)<(y)?(x):(y))

Upvotes: -2

Barry
Barry

Reputation: 303186

You cannot distinguish between a compile-time literal int and a run-time variable int. If you need to do this, you can provide an overload that can only work at compile-time:

void foo(int ); // run-time

template <int I>
void foo(std::integral_constant<int, I> ); // compile-time

Upvotes: 9

Related Questions