C++ 11样式SFINAE和模板实例化时的函数可见性

yur*_*hek 2 c++ templates sfinae argument-dependent-lookup c++11

我不确定这与sfinae有什么关系,或者只是与任何模板化函数相关的东西.我试图使用sfinae根据相应的自由函数的存在启用/禁用成员函数,而后者又基于另一种类型的成员函数的存在而启用/禁用,所有使用此处描述的方法:

struct S;

template <typename T>
inline auto f(S& s, T const& t)
   -> decltype(t.f(s), void())
{
   t.f(s);
}

struct S
{
    template <typename T>
    auto f(T const& t)
        -> decltype(f(*this, t), void())
    {
        f(*this, t); // <------------------------------------------- HERE
    }
};

struct pass
{
    void f(S&) const
    {
        //...
    }
};

struct fail
{
};

int main()
{
    S s;
    s.f(pass()); // should compile fine
    //s.f(fail()); // should fail to compile due to absence of f from S
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是gcc 4.7.1在箭头标记的行上给了我这个:

错误:没有匹配函数用于调用'S :: f(S&,const pass&)'
注意:候选者是:
注意:模板decltype((f((*this),t),void()))S :: f (const T&)
注意:模板参数推断/替换失败:
注意:候选人需要1个参数,2提供

这显然意味着全局f以上不考虑过载解决.

为什么这样做,我该怎么做才能做到这一点?

另外为什么上面两行没有错误,f在decltype中以类似的方式使用?

UPDATE

正如@nm所说,成员函数完全无阴影函数,即使它们的签名不同,所以这里的解决方法不会破坏ADL f(与@nm建议的全名资格不同).让free function(f_dispatcher)在某个地方没人会看(detail),并在里面完全限定它的名字S::f.在该函数中调用free f并让ADL从那里开始处理它,如下所示:

struct S;

template <typename T>
inline auto f(S& s, T const& t)
    -> decltype(t.f(s), void())
{
    t.f(s);
}

namespace detail
{
    template <typename T>
    inline auto f_dispatcher(S& s, T const& t)
        -> decltype(f(s, t), void())
    {
        f(s, t);
    }
}

struct S
{
    template <typename T>
    auto f(T const& t)
        -> decltype(detail::f_dispatcher(*this, t), void())
    {
        detail::f_dispatcher(*this, t);
    }
};

struct pass
{
    void f(S&) const
    {
        //...
    }
};

struct fail
{
};

int main()
{
    S s;
    s.f(pass()); // compiles fine
    //s.f(fail()); // fails to compile due to absence of f from S
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

n. *_* m. 6

这与SFINAE或模板或C++ 11或ADL无关.

无论类型如何,成员都会隐藏具有相同名称的所有非成员.如果您有一个名为的成员f,则不能引用任何非成员f,除非您使用限定名称(例如::f).

只是用::f(*this, t);.