Search code examples
c++templatesc++17autonon-type-template-parameter

Can C++ infer type of non-type template argument and enforce the type on the rest of template arguments?


Consider this struct. It is a range, but uses template instead of constructor, making the values static:

template <int min_v, int max_v>
struct num_range final {
  constexpr static int min = min_v;
  constexpr static int max = max_v;
}
// now you can do
std::cout << num_range<1,3>::min << '\n'; // prints 1

But this is fixed to int. What if I wanted C++ to deduce the numeric type from the first argument and enforce it on the second argument?

I tried this:

template <typename TNumber>
template <TNumber min_v, TNumber max_v>
struct num_range final 

I tried that at the reverse order. I know you can do this:

template <auto min_v, decltype(min_v) max_v>
struct num_range final {
    using num_type = decltype(min_v);
    constexpr static num_type min = min_v;
    constexpr static num_type max = max_v;
};

But I don't think auto template argument is allowed in C++17, which is what I am targeting. It also does not seem to enforce the type on the second template argument, as this compiles just fine:

std::cout << num_range<-10, 12U>::min << '\n'; // prints -10

Bonus points if you know how to do this with variadric template, enforcing all numbers to be same type.


Solution

  • I don't think auto template argument is allowed in C++17

    It is allowed in C++17.

    It also does not seem to enforce the type on the second template argument

    Yes, some implicit conversions are permitted when passing template arguments. Do this instead:

    template <auto min_v, auto max_v>
    struct num_range
    {
        static_assert(std::is_same_v<decltype(min_v), decltype(max_v)>);
        constexpr static auto min = min_v;
        constexpr static auto max = max_v;
    };
    

    Or in C++20:

    template <auto min_v, auto max_v>
    requires std::is_same_v<std::is_same_v<decltype(min_v), decltype(max_v)>
    struct num_range
    {
        constexpr static auto min = min_v;
        constexpr static auto max = max_v;
    };