13

C++03 允许您将函数参数限定为constvolatile和/或左值引用 ( &)。

C++11 又增加了一个:右值引用 ( &&)。

此外,C++ 允许您根据参数的限定符重载函数,以便在调用函数时选择最合适的重载。

成员函数在概念上可以被认为是一个接受额外参数的函数,其类型是对其所属类的实例的引用。可以像任何其他参数一样重载基于此“额外参数”的限定符的成员函数。这通过将限定符放在函数签名的末尾来表示:

struct Foo
{
    int& data();             // return a non-const reference if `this` is non-const
    const int& data() const; // return a const reference if `this` is const
};

在 C++03 中,constvolatile限定符是可能的,并且 C++11 也允许&&&&理论上在 C++03 中可以允许,但事实并非如此)。

可以使用任何限定符组合,除了&&&是互斥的,这使得 C++03 中的 2^2 = 4 种可能性和 C++11 中的 2^4-4 = 12 种可能性。

当您想使用成员函数指针时,这可能会很痛苦,因为它们在这些限定符中甚至没有一点多态性:this作为参数传递的成员函数指针的“类型”上的限定符必须完全匹配那些关于它被传递的参数的类型。C++ 也没有提供明确的工具来抽象限定符。在 C++03 中,这基本上没问题,因为您必须编写一个const版本和一个非const版本,而没有人关心volatile,但是在 C++11 中的病态情况下(这并不像病态那样罕见)您可能不得不手动编写多达 12 个重载。每个功能。

我很高兴地发现,如果您将封闭类的类型作为模板参数传递并从中派生成员函数指针的类型,则允许constvolatile限定符如您所期望的那样传播:

template<typename Object>
struct Bar
{
    typedef int (Object::*Sig)(int);
};

Bar<Baz>;                // Sig will be `int (Baz::*)(int)`
Bar<const Baz>;          // Sig will be `int (Baz::*)(int) const`
Bar<volatile Baz>;       // Sig will be `int (Baz::*)(int) volatile`
Bar<const volatile Baz>; // Sig will be `int (Baz::*)(int) const volatile`

这比手动写出所有案例要好得多。

不幸的是,它似乎不适用于&and &&

GCC 4.7 说:

错误:形成指向引用类型“Baz&&”的指针</p>

但这并不奇怪,因为 4.7 的 GCC 还不支持this.

我还尝试了 Clang 3.0,它确实有这样的支持:

错误:成员指针指向非类类型 'Baz &&'

那好吧。

我是否认为这是不可能的,并且无法在this type成员函数指针的 " " 上抽象出引用限定符,这是否正确?this除了在特定情况下将“this类型”作为模板参数传递时,任何其他用于抽象限定符(尤其是 on )的技术也将不胜感激。

(值得指出的是,如果 C++ 不区分成员函数和普通函数,这一切都是微不足道的:您将使用模板形参作为函数(指针)的形参类型,而模板形参将按原样通过,限定符完好无损,无需额外考虑。)

4

1 回答 1

4

您是否考虑过简单地专门化您的模板?

您可以添加两个版本:

template <typename Object>
struct Bar<Object&> {
  typedef int (Object::*Sig)(int)&;
};

template <typename Object>
struct Bar<Object&&> {
  typedef int (Object::*Sig)(int)&&;
};

然后编译器将适当地选择正确的专业化(或回退到一般情况)。

这使您免于const/volatile的事情,但确实意味着您需要编写 3 次代码。

于 2012-01-15T20:03:33.047 回答