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)
如果我注释掉的代码声明类D和D::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在模板派生类中声明,而在非模板类中它可以吗?
N3337 [dcl.fct]/10:oftypedef函数类型可用于声明函数,但不得用于定义函数。
根据这条规则, 和D在W技术上都是格式良好的。我认为这不能用 GCC 或 Clang 编译的原因是使用 typedef 声明函数的情况非常罕见。使用依赖于模板参数的成员 typedef 来声明函数的情况更加罕见。看起来您刚刚遇到了编译器支持有限的黑暗角落。
有趣的是,MSVC 实际上在这里做了正确的事情。
您最好的选择可能是找到一种不同的方式来表达您的课程。在不了解您要解决的问题的更多信息的情况下,我真的无法给出任何直接的建议,但如果您提出一个包含详细信息的新问题,我们可以提供一些建议。
编辑:
然而,正如 Jarod42 指出的那样,依赖类型稍后可以定义为函数类型以外的其他类型,从而使声明无效。MSVC 可以工作而 GCC 和 Clang 不能工作的原因与 MSVC 在某些地方不需要的原因相同typename:它没有正确实现两阶段查找。完全指定这种情况需要将function_typename依赖名称标记为函数类型。我认为声明基于依赖类型的函数是不明确且不一致的,因为这种情况非常罕见。