Есть ли способ проверить количество аргументов в списке std:: initializer во время компиляции?


Я пытаюсь создать функцию, которая принимала бы несколько аргументов данного типа, но и тип, и количество аргументов должны быть указаны с помощью шаблонов.

Я обнаружил, что использование C++11 initializer_list , вероятно, хороший метод в этом случае, но можно ли проверить его размер во время компиляции? Существуют ли какие-либо другие технологии, которые могут решить эту проблему?

#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"); 
    }
};
3 4

3 ответа:

Вы не можете статически утверждать количество времени выполнения. А количество значений в initializer_list определяется во время выполнения вызывающей функцией.

Даже создание вашей функции constexpr не будет работать, так как оценка функции не требуется, чтобы иметь место во время компиляции.

Вместо этого следует использовать вариадический шаблон.

Благодаря Николу я посмотрел в сторону вариадических шаблонов. Проблема состояла не только в том, чтобы проверить количество аргументов, но и в том, чтобы проверить, что их типы конвертируются в базовый тип. Вот мое решение, основанное наэтой иэтой темах. Он работает, как и ожидалось в 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"); 
    }
};

Добавление точки класса POD с элементами DIM data лучше всего подходит для вашей цели. Тогда неявный вызов конструктора удостоверится, что все в порядке.