“Overloading” constructors with SFINAE

一个人想着一个人 提交于 2019-12-10 19:42:06

问题


Why does the the following attempt at overloading the constructor Foo::Foo fail? Also, I'd appreciate alternatives/workarounds

#include <vector>
#include <type_traits>

namespace xyz
{   
    struct MemoryManager{};

    template<typename T , typename Alloc=MemoryManager>
    class vector
    {
    };
}


template<typename T, template<typename,typename> class V , typename A>
struct Foo
{
    template<typename U = T ,
             typename Dummy = typename std::enable_if<
                 std::is_same<std::vector<U>, V<U,A> >::value >::type >
    Foo() // when instantiated with the std vector
    {
    }

    template<typename U = T ,
             typename Dummy = typename std::enable_if<
                 std::is_same<xyz::vector<U>, V<U,A> >::value >::type >
    Foo() // when instantiated with my custom vector
    {
    }   
};

int main()
{
}

Error message:

23:3: error: ‘template<class T, template<class, class> class V, class A> template<class U, class Dummy> Foo<T, V, A>::Foo()’ cannot be overloaded
   Foo() // when instantiated with my custom vector

18:3: error: with ‘template<class T, template<class, class> class V, class A> template<class U, class Dummy> Foo<T, V, A>::Foo()’
   Foo() // when instantiated with the std vector

回答1:


You can't overload the constructors that way because default arguments are not part of the signature. Effectively, you have:

template <typename, typename>
Foo();

template <typename, typename>
Foo();

This rule may be clearer outside of the template world, where these two functions cannot overload each other:

void foo(int x = 42);
void foo(int y = 17);

You could instead make the 2nd template argument a defaulted non-type parameter, so that the two constructors have different signatures:

template<typename U = T , 
         std::enable_if_t<std::is_same<std::vector<U> , V<T,A> >::value, int> = 0>
Foo() // when instantiated with the std vector

Or you could delegate both constructors using a dummy type:

template <typename T> struct tag { };

Foo()
: Foo(tag<V<T,A>>{})
{ }

Foo(tag<std::vector<T>> )
{ /* std vector */ }

Foo(tag<xyz::vector<T>> )
{ /* your vector */ }


来源:https://stackoverflow.com/questions/31138449/overloading-constructors-with-sfinae

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!