繁体   English   中英

为什么类模板的成员函数声明必须格式正确?

[英]Why should the member function declarations of a class template be all well-formed?

OK,假设我要检查template参数是否具有嵌套的type / typedef XYZ。

template <class T>
struct hasXZY
{
   typedef char                  no;
   typedef struct { char x[2]; } yes;
   template <class U>
   static yes f(typename U::XYZ*);
   template <class /*U*/>
   static no  f(...);
   enum {value = sizeof(f<T>(0))==sizeof(yes)};
};

如预期般运作良好。

现在考虑一下:

template <class T>
struct hasXZY
{
   typedef char                  no;
   typedef struct { char x[2]; } yes;

   static yes f(typename T::XYZ*);
   static no  f(...);
   enum {value = sizeof(f(0))==sizeof(yes)};
};

hasXYZ<int>现在会导致编译时错误。 OK,f不是模板函数。 但是另一方面,当通过hasXYZ<int>::valuehasXYZ实例hasXYZ<int>::value ,编译器可以轻松地从候选列表中排除f(int::XYZ*) 我只是不明白为什么类模板中成员函数声明的实例化失败必须使整个类实例化失败。 有任何想法吗?

编辑:我的问题是:为什么成员函数声明都应该格式正确? 由于编译器仅在使用方法时实例化方法,因此为什么需要正确的声明。 将上面的example2视为此功能的可能用例。

仅当为函数重载解决方案创建候选集时才使用SFINAE。 在第一个示例中,您正在调用重载的f()函数,由于SFINAE,第一个函数被排除了。

在第二个示例中,实例化hasXZY时,必须正确定义其所有成员,并且模板参数的替换一定不会失败。 它适用于int :: XYZ。

由于替换失败,成员不会被排除在班级之外。

我不是C ++语言律师,但是我会尽力而为。

在第二个示例中,成员函数必须定义良好,因为一旦为int实例化hasXZY 它们就不再是模板函数 为了使自己信服,请“手动”替换T

struct hasXYZ
{
    typedef int                   T;
    typedef char                  no;
    typedef struct { char x[2]; } yes;

    static yes f(T::XYZ*);
    static no  f(...);
    enum {value = sizeof(f(0))==sizeof(yes)};
};

int main()
{
    std::cout << hasXYZ::value << "\n";
}

并观察到它无法编译,并且编译错误与以前相同(至少在GCC中):

foo.cc:9: error: ‘T’ is not a class or namespace

相比之下,第一个示例在手动实例化后进行编译并按预期运行; f成员仍以U为模板。

编辑:我的问题是:为什么成员函数声明都应该格式正确? 由于编译器仅在使用方法时实例化方法,因此为什么需要正确的声明。 将上面的example2视为此功能的可能用例。

当隐式实例化类模板专门化时,编译器必须检查该成员的完整声明器,因为它需要了解有关该声明的基本信息。 这样可以增加类模板专业化的规模。

如果检查声明部分发现它声明了一个数据成员,则该类的sizeof值可能会产生不同的值。 如果要声明一个函数指针,情况就是这样

yes (*f)(typename T::XYZ*);

C ++语言的定义方式是仅在解析整个声明后才知道声明的类型。

您可以争辩说您在其中放置了静态对象,因此在这种情况下,不需要计算它的大小。 需要名称查找知道什么名字hasXZY<T>::f指,并有被宣布为名称F。对于所有。 编译器将不会实例化hasXYZ::f的定义,而只会实例化声明的hasXYZ::f部分,以获取其类型并将其名称添加到类类型中以进行名称查找。 我相信在可能可行的特殊情况下支持延迟实例化名称声明会使C ++编译器和C ++规范的实现更加复杂,而没有可比的好处。

最后,在您尝试调用它的示例中,编译器必须实例化声明,因为它需要查找名称f ,为此,它需要知道该声明是函数还是其他东西。 因此,即使在理论上,我实际上也无法在不实例化声明的情况下看到您的示例无法工作的方式。 请注意,无论如何,这些都不会实例化函数的定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM