How can I prevent a variadic constructor from being preferred to the copy constructor?

You can use some ugly SFINAE with std::enable_if, but I’m not sure it is better than your initial solution (in fact, I’m pretty sure it’s worse!):

#include <memory>
#include <type_traits>

// helper that was not included in C++11
template<bool B, typename T = void> using disable_if = std::enable_if<!B, T>;

template<typename T>
struct Foo {

    Foo() = default;
    Foo(const Foo &) = default;

    template<typename Arg, typename ...Args, typename = typename
        disable_if<
            sizeof...(Args) == 0 &&
            std::is_same<typename
                std::remove_reference<Arg>::type,
                Foo
            >::value
        >::type
    >
    Foo(Arg&& arg, Args&&... args)
        : t(std::forward<Arg>(arg), std::forward<Args>(args)...) {}

    T t;
};

int main(int argc, char* argv[]) {
    Foo<std::shared_ptr<int>> x(new int(42));
    decltype(x) copy_of_x(x);
    decltype(x) copy_of_temp(Foo<std::shared_ptr<int>>(new int));
    return 0;
}

Leave a Comment