Перегрузка шаблона класса на основе наличия параметра, отличного от типа?

#c #c 11 #templates

#c #c 11 #шаблоны

Вопрос:

У меня есть шаблонный класс, который работает как таковой:

 template <typename T, std::size_t maxSize>
class Foo
{
    std::array<T, maxSize> arr; 
};
  

Я хотел бы создать перегрузку, в которой вы можете выбрать только передачу T и вместо этого получить вектор в качестве базового контейнера:

 template <typename T>
class Foo
{
    std::vector<T> arr; 
};
  

Как правильно это сделать?

Комментарии:

1. Вы бы согласились с созданием maxSize int , вместо size_t ?

2. Да, это было бы хорошо.

3. Вы бы согласились с одним классом, который содержит соответствующий элемент, в зависимости от того, указан ли второй параметр шаблона?

4. Было бы приемлемо Foo<T,0> использовать vector вместо array ? Массив нулевой длины не очень полезен, но я бы не стал считать «бесполезным», если вы не согласны. Более общий вопрос: есть ли какое-либо значение maxSize , которое разумно можно использовать для обозначения «использовать вектор» вместо указания размера массива?

Ответ №1:

Вы можете использовать пакет параметров для размера и специализироваться на 1 аргументе или 0 аргументах:

Сначала укажите значение по умолчанию, при котором не удается скомпилировать

 template <typename T>
struct always_false : std::false_type {};

template <typename T, std::size_t... Is>
class Foo {
    static_assert(always_false<T>::value, "too many sizes");
};
  

Затем частично специализируйтесь на одном или нулевом аргументе:

 template <typename T, std::size_t maxSize>
class Foo<T, maxSize> {
public:
    std::array<T, maxSize> arr;
};

template <typename T>
class Foo<T>
{
public:
    std::vector<T> arr;  
};
  

Демонстрация: https://godbolt.org/z/5bW9c7

Комментарии:

1. Плюс этого в том, что позже, когда вам понадобится двумерный массив, он просто работает.

2. Очень приятно. Вы можете упростить это еще больше, просто не определяя первичный. ДЕМОНСТРАЦИЯ . Кроме того, в будущем нет необходимости удалять один ответ и публиковать другой, вы можете отредактировать другой.

3. Более лаконичный и простой код, верно, но использование статического утверждения, как показано, выдает более приятное сообщение об ошибке при сбое. Буду иметь в виду другие советы, спасибо.

4. Хорошо, достаточно справедливо 🙂 Хорошее решение.