Search code examples
c++templatesc++17

Is it enough to have forward declaration of std::list to test whether a type T is std::list?


For compile time checker which tests whether a type T is std::list I've came up with this template:

#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;
}

And my question is: Is it necessary to have #include <list> or having forward declaration of std::list would be enough? (Because actually I also need to write similar templates for std::vector, std::map, std::set and so on. And I'am afraid if having included all those headers can potentially hit compilation time.):

#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;
}

Solution

  • Is it necessary to have #include or having forward declaration of std::list would be enough?

    Yes you would need to include those header(s) if you're using them in any way that require them to be complete. Basically, we pay for what we use.

    Baiscally, a forward declaration will work as long as those types need not be complete but if you're using them in a way that require them to be complete then yes, you would need to include the respective headers.

    In your example, you're not using the type T in a way that require them to be complete but note that forward declaring a standard container is not allowed.

    Also see Forward declare a standard container?