2

I'm attempting to write a function that forces constexpr evaluation via. a template. I wrote this, but it works only for int (beware, will give recursion depth errors with GCC):

#include <iostream>

template<int val>
constexpr int force_constexpr() { return val; }

constexpr int triangle(int n)
{
    return n ? n + triangle(n - 1) : 0;
}

int main(void)
{
    std::cout << force_constexpr<triangle(0x200)>() << '\n';
}

Note that this is for demonstration purposes only; I know that the triangle number can be calculated with (n+1)*n/2.

Then I attempted to write a generic function, however, that doesn't work as well. This is a plain error (not surprising, as it uses T before T is defined):

template<T val, typename T = decltype(val)>
constexpr T force_constexpr() { return val; }

as is this (which obviously won't work; it's a nested template):

template<typename T>
template<T val>
constexpr T force_constexpr() { return val; }

and this requires the type of the argument to be passed:

template<typename T, T val>
constexpr T force_constexpr() { return val; }

How can I do this without passing the type as a parameter to the template? Or, in other words, how can I deduce a template parameter type?

I'm looking for a C++11 solution but solutions for other standards are welcome.

S.S. Anne
  • 15,171
  • 8
  • 38
  • 76

2 Answers2

4

You're looking for auto template parameters, in C++17:

#include <iostream>

template<auto T>
auto *singleton()
{
    static const decltype(T) solo{T};

    return &solo;
}

int main()
{
    const int *p=singleton<42>();

    std::cout << "The meaning of life: " << *p << std::endl;

    return 0;
}

Specify the template parameter as auto, and use decltype to deduce its type.

I do not believe that this is possible before C++17, since this is precisely the use case for which auto template parameters were added to the standard. Couldn't do this, conceptually, before then.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
0

C++17 introduces auto as non type template parameter:

template <auto val>
constexpr auto force_constexpr() { return val; }

Before, you have indeed blocked with

template<typename T, T val>
constexpr T force_constexpr() { return val; }

You can introduce MACRO to simplify usage:

#define AUTO(v) decltype(v), (v)

And then

std::cout << force_constexpr<AUTO(triangle(0x200))>() << '\n';
Jarod42
  • 203,559
  • 14
  • 181
  • 302