代码之家  ›  专栏  ›  技术社区  ›  Joseph Garvin

为什么我不能在模板参数中向下转换指向成员的指针?

  •  5
  • Joseph Garvin  · 技术社区  · 14 年前

    如果我创建一个指向基成员的指针,我通常可以将其转换为指向派生成员的指针,但在下面的buzz之类的模板中使用时,则不会,其中第一个模板参数会影响第二个模板参数。我是在与编译器bug作斗争,还是标准确实要求它不起作用?

    struct Foo
    {
        int x;
    };
    
    struct Bar : public Foo
    {
    };
    
    template<class T, int T::* z>
    struct Buzz
    {
    };
    
    static int Bar::* const workaround = &Foo::x;
    
    int main()
    {
        // This works. Downcasting of pointer to members in general is fine.
        int Bar::* y = &Foo::x;
    
        // But this doesn't, at least in G++ 4.2 or Sun C++ 5.9. Why not?
        // Error: could not convert template argument '&Foo::x' to 'int Bar::*'
        Buzz<Bar, &Foo::x> test;
    
        // Sun C++ 5.9 accepts this but G++ doesn't because '&' can't appear in
        // a constant expression
        Buzz<Bar, static_cast<int Bar::*>(&Foo::x)> test;
    
        // Sun C++ 5.9 accepts this as well, but G++ complains "workaround cannot
        // appear in a constant expression"
        Buzz<Bar, workaround> test;
    
        return 0;
    }
    
    1 回复  |  直到 14 年前
        1
  •  5
  •   GManNickG    14 年前

    这是不允许的。根据第14.3.2/5节:

    对用作非类型模板参数的每个表达式执行以下转换。如果非类型模板参数无法转换为相应模板参数的类型,则说明程序格式错误。
    _对于整型或枚举型的非类型模板参数,应用整型提升(4.5)和整型转换(4.7)。
    对于类型指针到对象的非类型模板参数,应用资格转换(4.4)和数组到指针转换(4.2)。 对于对象类型引用的非类型模板参数,不适用转换。引用引用引用的类型可能比模板参数的类型(否则相同)更符合cv。模板参数直接绑定到模板参数,该参数必须是左值。
    对于指向函数的指针类型的非类型模板参数,仅应用指向指针的函数转换(4.3)。如果template参数表示一组重载函数(或指向此类函数的指针),则从该集合中选择匹配函数(13.4)。
    对于函数的类型引用的非类型模板参数,不应用转换。如果template参数表示一组重载函数,则从该集合(13.4)中选择匹配函数。
    对于指向成员函数的指针类型的非类型模板参数,不应用转换。如果template参数表示一组重载的成员函数,则从集合(13.4)中选择匹配的成员函数。
    艾斯 对于指向数据成员的类型指针的非类型模板参数,应用限定转换(4.4)。

    我强调了有关指向数据成员的指针的转换。请注意,您的转换(_§4.11/2)未列出。在C++ 0x中,在这方面仍然是相同的。