'C++ How to create a constant pointer to a function?
I want to have a class with a constant pointer to a function as a member. However, I'm instead creating functions with constant return values (a strange feature I just run into while debugging).
The troublesome declarations are:
// ...
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&)
);
};
// ...
Here's the minimal WORKING example without const's. I'm using 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;
}
Here's the BROKEN example with the added const's.
#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;
}
You should get a compilation error such as:
No matching constructor for initialization of 'const TimestampedValueMinHeap<pair<int, big_unsigned>, int>' (aka 'const TimestampedValueMinHeap<pair<int, unsigned long long>, int>')
However, it works if you simply cast the arguments.
// ...
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;
}
Solution 1:[1]
Try doing it in steps, it is more readable also,
using getValue_ptr_type = ComparableValue (*)(const T&);
using const_getValue_ptr_type = const getValue_ptr_type;
const_getValue_ptr_type getValue;
OR use EAST const (my favorite)
ComparableValue (* const getValue)(const T&);
big_unsigned (* const getTimestamp)(const T&);
https://godbolt.org/z/z7P6P3sKz
NOTE: @MatthewM. rightly says that it is not a matter of EAST const or const WEST. This the only right way (for one liners).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |