Search code examples
c++templatesconstructorperfect-forwarding

Perfect forwarding an STL container to a template class


Trying to use perfect forwarding to pass a sequence container to a class that is templated. For instance:

template<template<typename T, typename Alloc> class TContainer, class TObject> 
class A {
public:
    using ContType = TContainer<TObject, std::allocator<TObject>>;

    //This works for R-value references only
    explicit A(ContType&& container) : internalContainer(std::forward<ContType>(container)) {};

    //This does not work - how might I make it work?
    template <typename C>
    explicit A(C&& input) : internalContainer(std::forward<C>(input)) {}

private:
    ContType internalContainer;
};

I have a problem in that I am trying to define a perfect forwarding constructor, and am a little lost as how to do so.

I have read elsewhere on this site that you cannot pass explicit type arguments to constructors. Is the only way to do this to provide R-value and L-value constructors?


Solution

  • Simpler is indeed to use several overloads:

    template<template<typename T, typename Alloc> class TContainer, class TObject> 
    class A {
    public:
        using ContType = TContainer<TObject, std::allocator<TObject>>;
    
        // for R-value
        explicit A(ContType&& container) : internalContainer(std::move(container)) {}
    
        // for L-value
        explicit A(const ContType& container) : internalContainer(container) {}
    
    private:
        ContType internalContainer;
    };
    

    Else you might use forwarding reference and protect with SFINAE

    template<template<typename T, typename Alloc> class TContainer, class TObject> 
    class A {
    public:
        using ContType = TContainer<TObject, std::allocator<TObject>>;
    
        template <typename T,
                  std::enable_if_t<
                      !std::is_same<A, std::decay_t<T>::value // Protect copy constructor
                      && std::is_constructible<ContType, T&&>::value>, int> = 0>
        explicit A(T&& container) : internalContainer(std::forward<T>(container)) {}
    
    private:
        ContType internalContainer;
    };