c++templatesnon-type-template-parameter

Infer dependent non-type template parameters


A class is templated on an array which represents a particular configuration for the class. This allows the configuration to be checked at compile time. Here is a complete simplistic example:

#include <array>

template<std::size_t config_size, const std::array<int, config_size>& config>
class MyClass
{
public:
    MyClass();
private:
    static constexpr bool configIsValid() ;
};

template<std::size_t config_size, const std::array<int, config_size>& config>
MyClass<config_size, config>::MyClass()
{
    static_assert(configIsValid());
}

template<std::size_t config_size, const std::array<int, config_size>& config>
constexpr bool MyClass<config_size, config>::configIsValid()
{
    return (config.size() > 3);
}

int main()
{
    static constexpr std::array<int, 4> valid_config{1,2,3,4};
    MyClass<4, valid_config> a;
    
    static constexpr std::array<int, 3> invalid_config{5,6,7};
    // MyClass<3, invalid_config> b; // This will fail to compile

    return 0;
}

This is OK, but the first template argument can be inferred from the second, so I would prefer to write:

MyClass<config> m;

Instead of:

MyClass<config_size, config> m;

Is there any way to do this?

The array could possibly be wrapped, but I'm not able to use a different container.


Solution

  • The only way this can be achieved with templates is to use auto type:

    template<const auto& config>
    class MyClass
    

    and so on. Here is link to complete code: https://godbolt.org/z/j6EKW9aff

    Other approach is to use macro for template parameters, like this:

    #define CONFIG_PARAMS(a) a.size(), a
    
    MyClass<CONFIG_PARAMS(valid_config)> a;