繁体   English   中英

为什么声明顺序对于将成员函数指针作为模板参数传递很重要?

[英]Why is declaration order important for passing a member function pointer as a template argument?

看看这段代码:

template <typename T, void (T::*pfn)()> struct Testee {};

class Tester
{
private:
    void foo() {}
public:
    using type_t = Testee<Tester, &Tester::foo>;    
};

它成功地用g++ -std=c++14 -Wall -Wextra

但是,当我更改footype_t的顺序时,会发生错误:

$ cat test.cpp
template <typename T, void (T::*pfn)()> struct Testee {};

class Tester
{
public:
    using type_t = Testee<Tester, &Tester::foo>;
private:
    void foo() {}
};

int main()
{
}

$ g++ -std=c++14 -Wall -Wextra -pedantic test.cpp
test.cpp:6:36: error: incomplete type ‘Tester’ used in nested name specifier
     using type_t = Testee<Tester, &Tester::foo>;
                                    ^
test.cpp:6:47: error: template argument 2 is invalid
     using type_t = Testee<Tester, &Tester::foo>;
                                               ^

通常,类定义中的声明顺序对名称解析没有影响。 例如:

struct A // OK
{
    void foo(int a = val) { }
    static constexpr const int val = 42;
};

struct B // OK
{
    static constexpr const int val = 42;
    void foo(int a = val) { }
};

但是,它在这种情况下有效。 为什么?

这与模板无关。 你得到一个类似的错误

class Tester
{
public:
    using type_t = decltype(&Tester::foo);
private:
    void foo() {}
};

一个类确实是(标准9.2 / 2):

在函数体,默认参数,引用继承构造函数(12.9)的使用声明异常规范和非静态数据成员的括号或等于初始化器 (包括嵌套类中的这类事物)中被认为是完整的。

但是,成员类型的定义不在该列表中,因此它只能使用在该点之前声明的名称。

通常,类定义中的声明顺序没有效果。

这是夸大其词。 根据我的知识,允许在类定义中稍后出现的一些声明用法:

  • 默认参数(如您所述;但不是默认模板参数)
  • 在函数体,function-try-block或成员初始化器中使用
  • 类内初始化器(C ++ 11或更高版本)

而且,如上所述,数据成员的顺序影响构造和销毁顺序。 此外,翻译单元之间的重新排序可能会令人惊讶地导致ODR违规。

暂无
暂无

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

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