C++ 使用和重载基类的模板成员函数?

C++ 使用和重载基类的模板成员函数?,c++,overloading,template-function,using-declaration,member-functions,C++,Overloading,Template Function,Using Declaration,Member Functions,下面,structY重载X的成员函数f。这两个重载都是模板函数,但采用不同的参数(typename和int),以明确指定: struct X { template <typename> static bool f() { return true; } }; struct Y : public X { using X::f; template <int> static bool f() { return false; } }; int main(

下面,struct
Y
重载
X
的成员函数
f
。这两个重载都是模板函数,但采用不同的参数(
typename
int
),以明确指定:

struct X
{
    template <typename> static bool f() { return true; }
};

struct Y : public X
{
    using X::f;
    template <int> static bool f() { return false; }
};

int main()
{
    std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl;
}
i、 例如,只能看到
Y
的版本。我试过了

using X::template f;

相反,没有成功。非静态(模板)成员函数也是如此。那么这是一个bug吗?

最近,我根据另一个答案解释了这个难题

从#铿锵IRC频道:

[01:16:23] <zygoloid> Xeo: this is a weird corner of the language where clang conforms but the rule is silly
[01:16:31] <Xeo> ... really? :(
[01:16:45] <zygoloid> Xeo: when deciding whether a using-declaration is hidden, we're not allowed to look at the template-parameter-list (nor the return type, iirc)
[01:17:04] <zygoloid> so the derived class declaration of operator()(T) suppresses the using-declaration
[01:17:19] <Xeo> because it has the same signature / parameter types?
[01:17:40] <zygoloid> rigth
Xeo:这是语言中一个奇怪的角落,在那里,叮当声符合规则,但规则很愚蠢 [01:16:31] ... 真的?( [01:16:45]Xeo:在决定是否隐藏using声明时,我们不允许查看模板参数列表(也不允许查看返回类型iirc) [01:17:04]因此运算符()的派生类声明(T)禁止使用声明 [01:17:19]因为它具有相同的签名/参数类型? [01:17:40]正确 解决方法是在
使用衍生版本的类中定义
f
。相反,将其移动到辅助助手类中(在这种情况下,这会引发问题,您认为哪个定义应该获胜)

  • 请参见此处了解我之前的问题案例:

  • 下面是如何使用额外的基类修复它:


归功于@Xeo和世界上的人们发现了这个“愚蠢的规则”

对于C++11中存在这样一个约束并且没有放松,我感到非常失望(这可能有很好的理由,但我无法想象为什么)。我觉得它破坏了类层次结构的整个概念

无论如何,我发现了一个解决方法。我包括了另一个非静态函数
g
,以说明差异,因为这个例子是我的主要兴趣所在

template <typename Y>
struct X
{
    template <typename> static bool f() { return true; }
    template <typename>        bool g() { return true; }

    template <int I>
    static bool f() { return Y::template _f <I>(); }

    template <int I>
    bool g()
    {
        return static_cast <Y&>(*this).template _g <I>();
    }
};

class Y : public X <Y>
{
    friend class X <Y>;
    template <int> static bool _f() { return false; }
    template <int>        bool _g() { return false; }
};

int main()
{
    Y y;
    std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl;
    std::cout << y. g <void>() << " " << y. g <0>() << std::endl;
}
模板
结构X
{
模板静态bool f(){return true;}
模板bool g(){return true;}
模板
静态bool f(){return Y::template _f();}
模板
布尔g()
{
返回static_cast(*this).template_g();
}
};
Y类:公共X类
{
X类朋友;
模板静态bool\u f(){return false;}
模板bool_g(){return false;}
};
int main()
{
Y;

std::cout XNote中有趣的模板注意:我尝试了另一个版本,其中模板参数会自动推导,并且在两个编译器中都能工作(但我需要明确的规范)。@iavr:另一个注意事项是,您定义main()的方式“C++”编译器需要插入“<代码>返回0”;代码>如果程序员忽略了从<代码>()的返回语句。
@PetrBudnik:关于args列表呢?谢谢,所以我想这是个坏消息。你能更具体一点解决方法吗?你的意思是涉及lambdas吗?因为我需要显式指定的模板参数,我不知道这是怎么回事。@iavr我不可能知道,因为在你的例子中,函数模板完全隐藏了彼此r、 您可能应该使用SFINAE屏蔽重载的子集,以便“另一个”继承的模板可以启动。请确保SFINAE分支不重叠,否则您将以对
f
或(最佳情况)的不明确调用而告终据我所知,SFINAE没有可能检查的条件。这两个重载都同样有效,都应该由调用方指定。@iavr那么,根据定义,您不需要消除歧义吗?使用不同的函数名,添加一个
标记
模板参数,有效吗?我现在就要开始您的自我回答了,不是吗看到了吗earlier@sehe通过调用方显式指定模板参数来消除歧义(例如
f()
vs
f()
)。
template <typename Y>
struct X
{
    template <typename> static bool f() { return true; }
    template <typename>        bool g() { return true; }

    template <int I>
    static bool f() { return Y::template _f <I>(); }

    template <int I>
    bool g()
    {
        return static_cast <Y&>(*this).template _g <I>();
    }
};

class Y : public X <Y>
{
    friend class X <Y>;
    template <int> static bool _f() { return false; }
    template <int>        bool _g() { return false; }
};

int main()
{
    Y y;
    std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl;
    std::cout << y. g <void>() << " " << y. g <0>() << std::endl;
}