I am trying to create a function that would accept several arguments of a given type, but both type and number of arguments should be specified via templates.
I found that using C++11's initializer_list is probably a good technique in this case, but is it possible to check its size at compile time? Are there any other tecnhiques that can solve this problem?
#include <initializer_list>
// Here I want to define type and number of components for each point
template <typename T, int DIM>
class Geometry
{
public:
void addPoint(std::initializer_list<T> coords)
{
assert(coords.size() == DIM); // Working good, but not compile-time
// Next line does not compile because size() is not known at compile-time
static_assert(coords.size() == DIM, "Wrong number of components");
}
};
You cannot statically assert on a runtime quantity. And the number of values in an initializer_list
is decided at runtime, by the caller of the function.
Not even making your function constexpr
would work, since evaluation of the function is not required to take place at compile-time.
You should instead use a variadic template.
Thanks to Nicol, I looked towards the variadic templates. The problem was not only to check the number of arguments, but also to check that their types are convertible to the base type. Here's my solution based on this and this topics. It works as expected in GCC 4.9.
template<class T, class...>
struct are_convertible : std::true_type
{};
template<class T, class U, class... TT>
struct are_convertible<T, U, TT...>
: std::integral_constant<bool, std::is_convertible<T,U>{} && are_convertible<T, TT...>{}>
{};
template <typename T, int DIM>
class Geometry
{
public:
template<typename... Args>
void addPoint(Args... coords)
{
static_assert(sizeof...(coords) == DIM, "Number of components does not match template");
static_assert(are_convertible<T, Args...>{}, "All arguments' types must be convertible to the template type");
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With