gpt4 book ai didi

c++ - 虚函数和泛型编程

转载 作者:行者123 更新时间:2023-11-30 05:22:06 27 4
gpt4 key购买 nike

假设我有一个这样的模板类:

template <class T>
class Foo
{
public:

explicit Foo(const T& value)
: m_Value(value)
{
}

bool Bar(const T& value)
{
return m_Value == value;
}

private:

T m_Value;
};

假设我有一些其他用户类型,例如:

class A
{
};

那么这段代码是完全有效的,即使类 A 没有定义相等运算符:

int main(int argc, char* argv[])
{
A a;
Foo<A> foo(a);

return 0;
}

但是如果我将 Foo::Bar() 设为虚拟:

    virtual bool Bar(const T& value)
{
return m_Value == value;
}

代码不再编译:

错误 C2676:二进制“==”:“A”未定义此运算符或预定义运算符可接受的类型的转换

我完全理解为什么这是个问题。如果我错了请纠正我,但我的理解是因为该函数是虚拟的,编译器必须编译该函数(即使它从未被调用过)以便它可以在 Foo< 的 v-table 中引用它/strong>.

我想知道是否有办法解决这个问题。我想要一个模板类来处理可能只实现部分接口(interface)的泛型类型。只要不使用缺失的位,代码应该可以正常编译。这类似于许多 STD 容器已经工作的方式,但它们不使用虚函数。

我该怎么做?对此有优雅的解决方案吗?

最佳答案

正如上面 Kerrek SB 所解释的,当模板被实例化时,虚函数总是被实例化。所以没有办法让你的程序在不使用虚拟方法时编译得很好并且如果它被使用并且你想要包装的类不提供它自己的 operator== 则编译失败.

但是,您可以让程序在运行时崩溃(使用 assert/terminate )或抛出异常。

免责声明:我不认为做你想做的事是个好主意,因为它允许创建不支持他们声称提供的接口(interface)的类。使用以下内容需要您自担风险。

这里的方法是为您要提供的每个方法使用自定义类型特征,即使包装类本身没有实现它。在你上面的例子中,这只是 operator== ,相应的代码看起来像这样:

namespace traits {
template <typename T>
using operator_eq_t = decltype(std::declval<T>() == std::declval<T>());

template <typename, typename = void>
struct has_operator_eq : std::false_type {};

// check that operator== is defined and returns the correct type `bool`.
template <typename T>
struct has_operator_eq<T, std::void_t<operator_eq_t<T>>>
: std::is_same<operator_eq_t<T>, bool> {};
} // namespace traits

如果您无权访问 c++1z,但您可以制作自己的 std::void_t 版本,其他所有内容均适用于 C++14:

template <typename...>
using void_t = void

有了它,您就可以创建带有标签分派(dispatch)的包装器类模板:

template <typename T>
class Foo : public IFoo<T> {
public:
explicit Foo(T const& value)
: m_Value(value) {
}

bool Bar(T const& value) override {
return BarImpl(value, traits::has_operator_eq<T>{});
}

private:
T m_Value;

bool BarImpl(T const& value, std::false_type) {
// some sensible default, in this case you might
// consider just to return false
assert(!"Called `Bar` on class that does not implement `operator==`.");
throw std::logic_error("Called `Bar` on class that does not implement `operator==`.");
}

bool BarImpl(T const& value, std::true_type) {
return value == m_Value;
}
};

可以在 here 找到一个工作示例。

关于c++ - 虚函数和泛型编程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39823372/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com