8

Can I force compiler to accept only a constexpr or a non-variable input to a function?

I am looking for allowing only compile time values to a function. Either using template or any other method.

Here, there is a working example for int templates. The problem with doubles is that they cannot be used as template arguments.

#include <iostream>

template <double x>
void show_x()
{
    std::cout<<"x is always "<<x<<" in the entire program."<<std::endl;
}

int main()
{
    show_x<10.0>();
    return 0;
}

error: ‘double’ is not a valid type for a template non-type parameter


Update

To those who have marked this question as a duplicate, I have to say:

I ask question

How to solve problem A?

and

Solution B does not work for problem A, I need another solution

Then you linked me to why solution B does not work.

That is totally illogical.

14
  • 2
    @m.s., I do not ask why I cannot make template from double. I am asking how can I only allow compile time values to a function. Either using template or any other method. Commented Sep 11, 2016 at 7:25
  • To clarify, why can't you pass this as a normal function parameter? Commented Sep 11, 2016 at 7:33
  • @OliverCharlesworth, for security reasons. I am planning to use this function for time synchronization and the step time should not be variable otherwise an unpredictable behavior will happen. There is always a way to get around this problem. However, I prefer to solve it this way. Commented Sep 11, 2016 at 7:34
  • 1
    "for security reasons" ?? Though I also think this question should be reopened. Commented Sep 11, 2016 at 7:40
  • 1
    Another approach: use rational arithmetics and std::ratio. This is what standard library does when it needs compile-time fractional number. Commented Sep 11, 2016 at 8:00

2 Answers 2

5

I'm not sure exactly what you want, but here is a way to reject non-constant expressions in a function call. Unfortunately it uses a macro which is bad because of name pollution, but maybe if you give your function a strange name then it won't hurt too much:

void f(double d) {}
#define f(x) do { constexpr decltype(x) var = x; f(var); } while (0)

int main() 
{
    f(1.0);      // OK
    f(1 + 2);    // OK, constant expression with implicit conversion
    double e = 5.0;
    f(e);        // compilation error, `e` is not a constant expression
}

If you want to reject constant expressions which aren't exactly double type already, that would be possible too (not sure from your question whether that is a requirement).

Sign up to request clarification or add additional context in comments.

Comments

5

Here are 2 ways:

Update:

Concerns about user-circumvention have been addressed. Now, X::value() s acquired by a constexpr variable within the function body before being used. It is now not possible to pass an X without a constexpr method called value().

#include <iostream>


  struct always_10
  {
    constexpr static double value() { return 10.0; }
  };

template <class X>
void show_x()
{
  constexpr auto x = X::value();
  std::cout<<"x is always "<< x <<" in the entire program."<<std::endl;
}

template<class X>
void show_x(X x_)
{
  constexpr auto x = x_.value();
  std::cout<<"x is always "<< x <<" in the entire program."<<std::endl;
}

int main()
{
    show_x<always_10>();
    show_x(always_10());
    return 0;
}

3 Comments

Your method works fine. However, still constexpr is not a requirement for show_x. One user can get around the library by mistake.
@ar2015 I'm not sure i understand.
I think ar2015 is saying that this is a bit of a cheat because, rather than the function itself enforcing the constraint, you have to do it yourself by remembering to pass an object of a certain type that enforces the constraint. As such this may be a decent practical solution in many cases (and frankly I personally wouldn't bother going further than this), but I can see why ar2015 may believe that this doesn't really satisfy the spirit of the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.