C++ 如何创建指向函数的常量指针?
C++ How to create a constant pointer to a function?
我想要一个class,它的成员是一个指向函数的常量指针。但是,我正在创建具有常量 return 值 (a strange feature I just run into while debugging) 的函数。
麻烦的声明是:
// ...
template<typename T, typename ComparableValue>
class TimestampedValueHeap {
public:
TimestampedValueHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
protected:
const ComparableValue (*getValue)(const T&);
const big_unsigned (*getTimestamp)(const T&);
};
// ...
template<typename T, typename ComparableValue>
class TimestampedValueMinHeap : TimestampedValueHeap<T, ComparableValue> {
public:
TimestampedValueMinHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
};
// ...
这是没有常量的最小工作示例。我正在使用 C++14。
#include <utility>
using namespace std;
typedef unsigned long long big_unsigned;
template <typename T, typename U>
T getFirst(const pair<T, U>& x) {
return x.first;
}
template<typename T, typename U>
U getSecond(const pair<T, U>& x) {
return x.second;
}
// ==================================================
// TimestampedValueHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueHeap {
public:
TimestampedValueHeap(
ComparableValue (*)(const T&),
big_unsigned (*)(const T&)
);
protected:
ComparableValue (*getValue)(const T&);
big_unsigned (*getTimestamp)(const T&);
};
template<typename T, typename ComparableValue>
TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(
ComparableValue (*getValue)(const T&),
big_unsigned (*getTimestamp)(const T&)
): getValue(getValue), getTimestamp(getTimestamp) {
}
// ==================================================
// TimestampedValueMinHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueMinHeap : TimestampedValueHeap<T, ComparableValue> {
public:
TimestampedValueMinHeap(
ComparableValue (*)(const T&),
big_unsigned (*)(const T&)
);
};
template<typename T, typename ComparableValue>
TimestampedValueMinHeap<T, ComparableValue>::TimestampedValueMinHeap(
ComparableValue (*getValue)(const T&),
big_unsigned (*getTimestamp)(const T&)
): TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(getValue, getTimestamp) {
}
int main() {
const TimestampedValueMinHeap<pair<int, big_unsigned>, int> minHeap(
getFirst<int, big_unsigned>,
getSecond<int, big_unsigned>
);
return 0;
}
这是添加了常量的 BROKEN 示例。
#include <utility>
using namespace std;
typedef unsigned long long big_unsigned;
template <typename T, typename U>
T getFirst(const pair<T, U>& x) {
return x.first;
}
template<typename T, typename U>
U getSecond(const pair<T, U>& x) {
return x.second;
}
// ==================================================
// TimestampedValueHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueHeap {
public:
TimestampedValueHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
protected:
const ComparableValue (*getValue)(const T&);
const big_unsigned (*getTimestamp)(const T&);
};
template<typename T, typename ComparableValue>
TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(
const ComparableValue (*getValue)(const T&),
const big_unsigned (*getTimestamp)(const T&)
): getValue(getValue), getTimestamp(getTimestamp) {
}
// ==================================================
// TimestampedValueMinHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueMinHeap : TimestampedValueHeap<T, ComparableValue> {
public:
TimestampedValueMinHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
};
template<typename T, typename ComparableValue>
TimestampedValueMinHeap<T, ComparableValue>::TimestampedValueMinHeap(
const ComparableValue (*getValue)(const T&),
const big_unsigned (*getTimestamp)(const T&)
): TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(getValue, getTimestamp) {
}
int main() {
const TimestampedValueMinHeap<pair<int, big_unsigned>, int> minHeap(
getFirst<int, big_unsigned>,
getSecond<int, big_unsigned>
);
return 0;
}
你应该得到一个编译错误,例如:
No matching constructor for initialization of 'const TimestampedValueMinHeap<pair<int, big_unsigned>, int>' (aka 'const TimestampedValueMinHeap<pair<int, unsigned long long>, int>')
但是,如果您简单地转换参数,它就会起作用。
// ...
int main() {
const TimestampedValueMinHeap<pair<int, big_unsigned>, int> minHeap(
(const int (*)(const pair<int, big_unsigned>&)) getFirst<int, big_unsigned>,
(const big_unsigned (*)(const pair<int, big_unsigned>&)) getSecond<int, big_unsigned>
);
return 0;
}
尝试按步骤进行,它也更具可读性,
using getValue_ptr_type = ComparableValue (*)(const T&);
using const_getValue_ptr_type = const getValue_ptr_type;
const_getValue_ptr_type getValue;
或者使用 EAST const(我最喜欢的)
ComparableValue (* const getValue)(const T&);
big_unsigned (* const getTimestamp)(const T&);
https://godbolt.org/z/z7P6P3sKz
注意:@MatthewM。正确地说,这不是 EAST const 或 const WEST 的问题。这是 唯一 正确的方式(对于一个班轮)。
我想要一个class,它的成员是一个指向函数的常量指针。但是,我正在创建具有常量 return 值 (a strange feature I just run into while debugging) 的函数。
麻烦的声明是:
// ...
template<typename T, typename ComparableValue>
class TimestampedValueHeap {
public:
TimestampedValueHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
protected:
const ComparableValue (*getValue)(const T&);
const big_unsigned (*getTimestamp)(const T&);
};
// ...
template<typename T, typename ComparableValue>
class TimestampedValueMinHeap : TimestampedValueHeap<T, ComparableValue> {
public:
TimestampedValueMinHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
};
// ...
这是没有常量的最小工作示例。我正在使用 C++14。
#include <utility>
using namespace std;
typedef unsigned long long big_unsigned;
template <typename T, typename U>
T getFirst(const pair<T, U>& x) {
return x.first;
}
template<typename T, typename U>
U getSecond(const pair<T, U>& x) {
return x.second;
}
// ==================================================
// TimestampedValueHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueHeap {
public:
TimestampedValueHeap(
ComparableValue (*)(const T&),
big_unsigned (*)(const T&)
);
protected:
ComparableValue (*getValue)(const T&);
big_unsigned (*getTimestamp)(const T&);
};
template<typename T, typename ComparableValue>
TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(
ComparableValue (*getValue)(const T&),
big_unsigned (*getTimestamp)(const T&)
): getValue(getValue), getTimestamp(getTimestamp) {
}
// ==================================================
// TimestampedValueMinHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueMinHeap : TimestampedValueHeap<T, ComparableValue> {
public:
TimestampedValueMinHeap(
ComparableValue (*)(const T&),
big_unsigned (*)(const T&)
);
};
template<typename T, typename ComparableValue>
TimestampedValueMinHeap<T, ComparableValue>::TimestampedValueMinHeap(
ComparableValue (*getValue)(const T&),
big_unsigned (*getTimestamp)(const T&)
): TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(getValue, getTimestamp) {
}
int main() {
const TimestampedValueMinHeap<pair<int, big_unsigned>, int> minHeap(
getFirst<int, big_unsigned>,
getSecond<int, big_unsigned>
);
return 0;
}
这是添加了常量的 BROKEN 示例。
#include <utility>
using namespace std;
typedef unsigned long long big_unsigned;
template <typename T, typename U>
T getFirst(const pair<T, U>& x) {
return x.first;
}
template<typename T, typename U>
U getSecond(const pair<T, U>& x) {
return x.second;
}
// ==================================================
// TimestampedValueHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueHeap {
public:
TimestampedValueHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
protected:
const ComparableValue (*getValue)(const T&);
const big_unsigned (*getTimestamp)(const T&);
};
template<typename T, typename ComparableValue>
TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(
const ComparableValue (*getValue)(const T&),
const big_unsigned (*getTimestamp)(const T&)
): getValue(getValue), getTimestamp(getTimestamp) {
}
// ==================================================
// TimestampedValueMinHeap
// ==================================================
template<typename T, typename ComparableValue>
class TimestampedValueMinHeap : TimestampedValueHeap<T, ComparableValue> {
public:
TimestampedValueMinHeap(
const ComparableValue (*)(const T&),
const big_unsigned (*)(const T&)
);
};
template<typename T, typename ComparableValue>
TimestampedValueMinHeap<T, ComparableValue>::TimestampedValueMinHeap(
const ComparableValue (*getValue)(const T&),
const big_unsigned (*getTimestamp)(const T&)
): TimestampedValueHeap<T, ComparableValue>::TimestampedValueHeap(getValue, getTimestamp) {
}
int main() {
const TimestampedValueMinHeap<pair<int, big_unsigned>, int> minHeap(
getFirst<int, big_unsigned>,
getSecond<int, big_unsigned>
);
return 0;
}
你应该得到一个编译错误,例如:
No matching constructor for initialization of 'const TimestampedValueMinHeap<pair<int, big_unsigned>, int>' (aka 'const TimestampedValueMinHeap<pair<int, unsigned long long>, int>')
但是,如果您简单地转换参数,它就会起作用。
// ...
int main() {
const TimestampedValueMinHeap<pair<int, big_unsigned>, int> minHeap(
(const int (*)(const pair<int, big_unsigned>&)) getFirst<int, big_unsigned>,
(const big_unsigned (*)(const pair<int, big_unsigned>&)) getSecond<int, big_unsigned>
);
return 0;
}
尝试按步骤进行,它也更具可读性,
using getValue_ptr_type = ComparableValue (*)(const T&);
using const_getValue_ptr_type = const getValue_ptr_type;
const_getValue_ptr_type getValue;
或者使用 EAST const(我最喜欢的)
ComparableValue (* const getValue)(const T&);
big_unsigned (* const getTimestamp)(const T&);
https://godbolt.org/z/z7P6P3sKz
注意:@MatthewM。正确地说,这不是 EAST const 或 const WEST 的问题。这是 唯一 正确的方式(对于一个班轮)。