Search code examples
c++templatesredefinition

Why this code is NOT causing redefinition error?


#include <initializer_list>

struct Foo
{
    template <typename T>
    Foo(std::initializer_list<T>) {}

    template <typename T>
    Foo(std::initializer_list<typename T::BarAlias>) {}
};

struct Bar
{
    using BarAlias = Bar; 
};

int main()
{
    Foo foo{ Bar{} };
}

I believe that a compiler should produce two exactly the same constructors inside of Foo. Why is it even working?


Solution

  • You have two templates with unrelated template arguments Ts. For the second constructor to be a candidate, T should be deducible, at least. However, in

    template <typename T>
    Foo(std::initializer_list<typename T::BarAlias>) {}
    

    T is in a non-deduced context. As a result, this constructor will always be rejected thanks to SFINAE.

    Note how your code is different from

    template<class T>
    struct Foo {
        Foo(std::initializer_list<T>);
        Foo(std::initializer_list<typename T::BarAlias>);
    };
    

    which for Foo<Bar> foo{Bar{}}; will indeed produce an error that you expect.