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 的问题。这是 唯一 正确的方式(对于一个班轮)。