Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

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.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#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 :

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

east const

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading