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