c++template-argument-deductionfunction-templatesnon-type-template-parameter

deducing non-type template argument type from template function argument


I have a template function parametrized by a compile-time constant whose type should be the same as the type of the function argument.

For instance, I'm seeking to have this kind of syntax:

#include <cstdint>
#include <limits>

using mytype_t = std::uint8_t;
constexpr mytype_t Min = 0;

template <typename T, T limit>
bool GreaterThanLimit(T const x) {
    if constexpr (limit > std::numeric_limits<T>::min()) {
        return (limit <= x);
    } else {
        return true;
    }
}

int main() {
    mytype_t x = 42;
    // KO
    bool v = GreaterThanLimit<Min>(x);
    static_cast<void>(v);
}

Non working Live

This dummy function is taking some runtime value x and a compile-time constant, that I want to be of the same type as x (let say it is an integral type), and tells if x is greater or equal than its limit.

How can I achieve that (C++14 if possible, C++17 at most)?


Solution

  • With auto template argument in C++17, things will do:

    #include <cstdint>
    #include <limits>
    #include <type_traits>
    
    using mytype_t = std::uint8_t;
    constexpr mytype_t Min = 0;
    
    template <auto limit, typename T> bool GreaterThanLimit(T const x) {
      static_assert(std::is_same_v<decltype<limit>,T>);
    
      if constexpr (limit > std::numeric_limits<T>::min()) {
        return (limit <= x);
      } else {
        return true;
      }
    }
    
    int main() {
      int x = 42;
    
      // Works
      bool v = GreaterThanLimit<Min>(x);
      static_cast<void>(v);
    }
    
    ❯ g++ -std=c++17 test.cpp -o test
    ❯ ./test
    ❯ echo $?
    0