其他分享
首页 > 其他分享> > C 11样式SFINAE和模板实例化时的功能可见性

C 11样式SFINAE和模板实例化时的功能可见性

作者:互联网

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

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;
}

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

error: no matching function for call to ‘S::f(S&, const pass&)’

note: candidate is:

note: template decltype ((f((* this), t), void())) S::f(const T&)

note: template argument deduction/substitution failed:

note: candidate expects 1 argument, 2 provided

这显然意味着上面的全局f不被考虑用于重载决策.

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

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

UPDATE

作为@ n.m.说,成员函数完全没有阴影自由函数,即使它们的签名不同,所以这里的解决方法不会破坏AD的ADL(与@n.m建议的全名资格不同).使自由函数(f_dispatcher)在任何人看不到(细节),并在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;
}

解决方法:

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

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

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

标签:c,c11,templates,sfinae,argument-dependent-lookup
来源: https://codeday.me/bug/20191002/1844408.html