Достаточно ли предварительного объявления std::list, чтобы проверить, является ли тип T std::list?

Для проверки времени компиляции, которая проверяет, является ли тип Tstd::list, я придумал этот шаблон:

#include <list>;

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

template <typename T, typename Allocator>
struct is_std_list<std::list<T, Allocator>>: std::true_type
{};

template <typename T>
inline constexpr bool is_std_list_v = is_std_list<T>::value;

int main()
{
    static_assert(is_std_list_v<std::list<int>>);
    return 0;
}

И мой вопрос: необходимо ли иметь #include <list> или предварительного объявления std::list будет достаточно? (Потому что на самом деле мне также нужно написать аналогичные шаблоны для std::vector, std::map, std::set и т. д. И я боюсь, что включение всех этих заголовков потенциально может привести к увеличению времени компиляции.):

#include <memory>;

namespace std
{
template <class T, class Allocator = allocator<T>>
class list;
}

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

template <typename T, typename Allocator>
struct is_std_list<std::list<T, Allocator>>: std::true_type
{};

template <typename T>
inline constexpr bool is_std_list_v = is_std_list<T>::value;

int main()
{
    static_assert(is_std_list_v<std::list<int>>);
    return 0;
}

Да, вам нужно будет включить эти заголовки, если вы используете их каким-либо образом, требующим их полноты. По сути, мы платим за то, что используем.

user12002570 13.06.2024 17:12

Направление объявления чего-либо из std является неопределенным поведением: stackoverflow.com/questions/307343/…

Yksisarvinen 13.06.2024 17:17

Технически, предварительного объявления достаточно, но у нас нет специального заголовка с форвардным объявлением для std::list (std::set и т. д.), поэтому вам придется включить <list>. Для библиотеки ввода-вывода есть заголовок <iosfwd>, но нет для других компонентов.

Evg 13.06.2024 17:18
godbolt.org/z/8nfE895Mb так что не получается
Marek R 13.06.2024 17:38

Помимо того, что это запрещено стандартом, существует также проблема, заключающаяся в том, что параметры по умолчанию могут быть объявлены только один раз. Таким образом, если в предварительном объявлении распределитель задан по умолчанию, его нельзя повторить в «настоящем» объявлении. Большая проблема!

BoP 13.06.2024 19:42
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
5
88
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Необходимо ли иметь #include или достаточно иметь предварительное объявление std::list?

Да, вам нужно будет включить эти заголовки, если вы используете их каким-либо образом, требующим их полноты. По сути, мы платим за то, что используем.

На самом деле, предварительное объявление будет работать до тех пор, пока эти типы не обязательно будут полными, но если вы используете их так, чтобы они были полными, тогда да, вам нужно будет включить соответствующие заголовки.

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

Также смотрите Вперед объявить стандартный контейнер?

Не уверен, что это важно, но std::is_same явно не указывает, что любой тип должен быть полным в столбце комментариев, в то время как все остальные признаки в таблице указаны: eel.is/c++draft/type.traits# вкладка:meta.rel

François Andrieux 13.06.2024 17:17

В общем, предварительного объявления достаточно, но это не вариант для стандартных классов, поскольку не существует законного способа их предварительного объявления.

К ним и namespace std могут быть прикреплены или не быть аннотации, специфичные для компилятора, и у вас могут возникнуть или не возникнуть проблемы из-за того, что вы не дублируете эти аннотации в своих предварительных объявлениях.


Лучшее решение здесь — вместо проверки всех отдельных контейнеров — проверить их свойства (например, наличие методов .begin() и .end()). Возможно, std::ranges::input_range — это то, что вам нужно, например.

Другие вопросы по теме

Рекурсивный шаблон C++ с переменным числом вариантов
Ошибка компиляции при использовании функций шаблона C++, которые принимают в качестве аргументов другие функции, которые принимают ссылки на указатели
Специализация шаблона вне встроенного пространства имен функции, определенной внутри встроенного пространства имен
Как вывести в шаблон имя текущего тега? (Тот, в котором мы находимся)
Может ли быть нарушено ODR, если определение шаблона создается только с разными параметрами?
Вывести параметры шаблона для параметра шаблона std::variant
Функция constexpr, которая продолжает умножать число до тех пор, пока оно не станет «достаточно большим»
Требуется ли для создания экземпляров шаблонов классов использовать только указатель или ссылку на них?
Как объявить конструктор с аргументами ровно nRow*nCol типа T?
Вывод шаблонной структуры в параметрах шаблонных функций