C++03允许将函数参数限定为const、volatile和/或lvalue引用(&)。
C++11再添加一个: rvalue引用(&&)。
此外,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中,const和volatile限定符是可能的,C++11也允许&和&& (理论上&在C++03中是允许的,但它不是)。
可以使用任何限定符的组合,但&和&&是相互排斥的,这使得2^2 =4在C++03中的可能性和2^4-4 = 12在C++11中成为可能。
当您想使用成员函数指针时,这可能会很痛苦,因为它们在这些限定符中甚至一点都不是多态的:作为参数传递的成员函数指针的"this类型“上的限定符必须与传递给它的参数类型上的限定符完全匹配。C++也没有提供任何明显的工具来对限定符进行抽象。在C++03中,这基本上是可以的,因为您必须编写一个const版本和一个非const版本,而且没有人关心volatile,但是在C++11的病理案例中(这种情况并不像病理一样罕见),您可能需要手动编写多达12个重载。每种功能。
我很高兴地发现,如果您将封装类的类型作为模板参数传递,并从中派生成员函数指针的类型,那么const和volatile限定符将如您所期望的那样被允许和传播:
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`这比手工写出所有的案例要好得多。
不幸的是,它似乎不适用于&和&&。
GCC 4.7说:
错误:形成指向引用类型‘Baz&&’的指针
但这并不奇怪,因为GCC在4.7岁的时候还没有支持this的参考限定符。
我也在Clang 3.0中试用了它,它确实有这样的支持:
错误:成员指针引用非类类型'Baz &&‘
哦,好吧。
我是否正确地得出这样的结论:这是不可能的,并且没有办法在成员函数指针的"this type“上抽象过引用限定符吗?当您将"this类型“作为模板参数传递时,除了在特定情况下,任何用于对限定符进行抽象的其他技术(特别是在this上)也会受到欢迎。
(值得指出的是,如果C++没有区分成员函数和正常函数,这一切都是微不足道的:您将使用模板参数作为函数(指针)的参数类型,模板参数将以原样传递,限定符完好无损,无需额外考虑。)
发布于 2012-01-15 20:03:33
你考虑过简单地专门化你的模板吗?
您只需添加以下两个版本:
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次代码。
https://stackoverflow.com/questions/8872550
复制相似问题