为什么模板类中的函数声明无效?

Rus*_*lan 8 c++ methods templates types

请考虑以下代码:

template<int X, int Y>
struct S
{
    typedef int func(int,float) const;
};

template<int X>
struct D : public S<X,6>
{
    typename S<X,6>::func func;
};
template<int X>
int D<X>::func(int,float) const
{
    return 1;
}
//----------------
struct W : public S<7,8>
{
    S<7,8>::func func;
};
int W::func(int,float) const
{
    return 2;
}

#include <iostream>
int main()
{
    W w;
    std::cout << w.func(1,4.3) << "\n";
    D<3> d;
    std::cout << d.func(1,4.3) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

如果我注释掉的代码声明类DD::func(),以及在相应的行main(),代码编译正常,我看到2在输出,符合市场预期.

但是当我创建派生类模板(typename在函数声明之前添加,作为S<X.6>依赖范围)时,我得到以下错误:

test.cpp:13:27: error: no ‘int D<X>::func(int, float) const’ member function declared in class ‘D<X>’
 int D<X>::func(int,float) const
                           ^
test.cpp: In instantiation of ‘struct D<3>’:
test.cpp:32:10:   required from here
test.cpp:10:27: error: field ‘D<3>::func’ invalidly declared function type
     typename S<X,6>::func func;
                           ^
Run Code Online (Sandbox Code Playgroud)
  • 为什么我不能func在模板派生类中声明,而在非模板类中它可以吗?
  • 究竟什么是"无效声明的函数类型"?什么是无效的?

Tar*_*ama 3

N3337 [dcl.fct]/10:oftypedef函数类型可用于声明函数,但不得用于定义函数。

根据这条规则, 和DW技术上都是格式良好的。我认为这不能用 GCC 或 Clang 编译的原因是使用 typedef 声明函数的情况非常罕见。使用依赖于模板参数的成员 typedef 来声明函数的情况更加罕见。看起来您刚刚遇到了编译器支持有限的黑暗角落。

有趣的是,MSVC 实际上在这里做了正确的事情

您最好的选择可能是找到一种不同的方式来表达您的课程。在不了解您要解决的问题的更多信息的情况下,我真的无法给出任何直接的建议,但如果您提出一个包含详细信息的新问题,我们可以提供一些建议。

您可能还考虑提交GCCClang的错误报告。


编辑:

然而,正如 Jarod42 指出的那样,依赖类型稍后可以定义为函数类型以外的其他类型,从而使声明无效。MSVC 可以工作而 GCC 和 Clang 不能工作的原因与 MSVC 在某些地方不需要的原因相同typename:它没有正确实现两阶段查找。完全指定这种情况需要将function_typename依赖名称标记为函数类型。我认为声明基于依赖类型的函数是不明确且不一致的,因为这种情况非常罕见。

  • 即使“function_typename”也不够,签名可能与定义不同(或者需要新的定义来进行专门化)。 (2认同)