Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Force compiler to accept only compile time argument (floating point)

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.

like image 282
ar2015 Avatar asked Sep 11 '16 07:09

ar2015


2 Answers

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;
}
like image 54
Richard Hodges Avatar answered Nov 01 '22 10:11

Richard Hodges


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).

like image 29
M.M Avatar answered Nov 01 '22 09:11

M.M