是否可以安全地在C ++中的两个函数指针之间进行转换,因为参数是多态等效的,即(仅示例)
class Base {}
class A : Base {}
class B : Base {}
class C : Base {}
template<typename T, typename U>
using FPTR = void (*)(const T&, const U&);
using index = std::pair<std:type_info, std::type_info>;
std::unordered_map<index, FPTR<Base, Base>> func_map;
template<typename T, typename U>
register(FPTR<T,U> fptr) {
// assert T and U are subclasses of Base
func_map[index(typeid(T), typeid(U))] = fptr;
}
void call(const Base& first, const Base& second) {
auto it = func_map.find(index(typeid(first), typeid(second)));
if (it != func_map.end()) {
(*it)(first, second)
}
}
void func1(const A&, const C&) {}
// call these
register<A,C>(func1);
register<B,B>([](const B&, const B&) -> void {});
因此,在调用call时,它会根据已注册的typeid解析要调用的函数,并且被调用的函数会期望显式类型,从基类型中有效地进行转换。
我的想法是,这会在运行时导致错误,因为强制转换正确。我考虑过使用lambda函数来包装fptr,但这会产生一个额外的间接调用,有没有办法在正确执行强制转换的同时避免这种情况,注意我无法投入调用,因为我只能获取typeid / type_info,并且不能将其与强制转换函数一起使用。
答案 0 :(得分:2)
如果这不是问题,你可以通过额外的直接调用来实现(目标调用甚至可以在包装器中嵌入,具体取决于你的编译器以及如何设置翻译单元。)
类似的东西:
struct Base {}
// ...
template <typename T, typename U>
using FPTR = void (*)(const T&, const U&);
template <typename T, typename U, FPTR<T,U> fptr>
void WrapFPTR(const Base &a, const Base &b)
{
fptr(static_cast<const T&>(a), static_cast<const U&>(b));
}
允许您在注册指定函数WrapFPTR<T,U,foo>
的每个网站上存储 FPTR<Base,Base>
的{{1}}。
如果你真的需要一个任意的函数指针,你需要存储一个多态闭包对象,并指向该函数的具体类型。
答案 1 :(得分:0)
当前的C ++没有包含co(ntra)方差的详细概念。你可以改用静态映射吗?
#include <iostream>
class Base {};
class A : Base {};
class B : Base {};
class C : Base {};
template<typename T, typename U> using FPTR = void (*)(const T&, const U&);
// instead of allocating a run-time map, create a map on compiler's heap at compile-time
template<typename U, typename V> static FPTR<U const &, V const &> funcMap;
void nyan(A const &, A const &) { std::cout << "Nyan" << std::endl; }
void meow(B const &, B const &) { std::cout << "Meow" << std::endl; }
int main() {
funcMap<A, A> = nyan;
funcMap<B, B> = meow;
funcMap<A, A>(A{}, A{});
}