#include <memory>
#include <utility>
#include <string>
#include <cassert>

enum GLenum { foo };

// this class doesn't have any default, copy constructors.
struct Dep
{
    Dep(std::string path, GLenum type) {}
    Dep() = delete;
    Dep(Dep const&) = delete;
};

struct Program
{
    std::shared_ptr<Dep> dep1;
    std::shared_ptr<Dep> dep2;

#if 1
    template <class T, class = typename std::enable_if<std::is_constructible<std::shared_ptr<Dep>, T>::value>::type>
    Program(T&& dep1, T&& dep2)
        : dep1(std::forward<T>(dep1)), dep2(std::forward<T>(dep2))
    {
    }
#else
    Program(std::shared_ptr<Dep> dep1, std::shared_ptr<Dep> dep2)
        : dep1(std::move(dep1)), dep2(std::move(dep2))
    {
    }
#endif
};

int main()
{
    auto dep1 = std::make_shared<Dep>("dep1", foo);
    auto dep2 = std::make_shared<Dep>("dep2", foo);
    Program p(std::move(dep1), std::move(dep2));

    assert(!dep1 && !dep2);
}

