调用未专门模板化的函数

问题描述 投票:1回答:2

我有一堆检查各种形状之间的碰撞的函数。

bool Collides(Rect r, Circle c);
bool Collides(Rect r, Line l);
bool Collides(Line l, Circle c);

我希望我可以实现一个模板功能,通过允许它交换输入参数,可以将实现数量减少一半。这样就不必执行:

// The same as before but the input parameters swapped
bool Collides(Circle c, Rect r) { return Collides(r, c); }
bool Collides(Line l, Rect r) { return Collides(r, l); }
bool Collides(Circle c, Line l) { return Collides(l, c); }

我可以改写一次:

template <typename Shape1, typename Shape2>
bool Collides(Shape1 a, Shape2 b)
{
    return Collides(b, a);
}

[不幸的是,当两个Collides(a, b)Collides(b, a)都未实现时,它在运行时递归地调用了模板化函数,这显然是意外行为。

是否有一些C ++标记或功能允许您关闭或禁止指定行或块的参数类型推导?目的是迫使编译器寻找非模板实现,然后如果不存在则无法编译。

c++ templates template-meta-programming
2个回答
3
投票

无法从重载集中删除功能模板。在您的特定情况下,有一些解决方法,例如:

struct CollidesImpl {
    bool operator()(Rect r, Circle c);
    bool operator()(Rect r, Line l);
    bool operator()(Line l, Circle c);
};

template <typename Shape1, typename Shape2>
bool Collides(Shape1 a, Shape2 b)
{
    static_assert(std::is_invocable_v<CollidesImpl, Shape1, Shape2> ||
                  std::is_invocable_v<CollidesImpl, Shape2, Shape1>,
                  "No implementation exists for these argument types");
    if constexpr(std::is_invocable_v<CollidesImpl, Shape1, Shape2>) {
        return CollidesImpl{}(a, b);
    } else {
        return CollidesImpl{}(b, a);
    }
}

0
投票

一次不查找功能模板是在功能声明期间(在打开{之前)。利用这一点,我们可以将未实现的参数SFINAE删除:

template<typename Shape1, typename Shape2>
auto Collides(Shape1 a, Shape2 b) -> decltype(::Collides(b, a)) {
    return Collides(b, a);
}
© www.soinside.com 2019 - 2024. All rights reserved.