限制模板参数是不好的做法吗?

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

在 C++ 中,根据 此来源 假设模板参数具有某些字段或方法是合法的。如果没有,它就会编译失败。

template<class Container>
void draw_all(Container& c)
{
    for_each(c.begin(),c.end(),mem_fun(&Shape::draw));
}

在此示例中,

Container
必须实现
begin()
end()
才能编译程序。然而,看看函数的原型,似乎没有明显的限制。

换句话说,有关接口使用的信息与实现交织在一起(即使使用

static_assert
)。

对我来说,这似乎是一种不好的做法(尽管我自己也遇到过它仍然是我能找到的最优雅的解决方案的情况)。是吗?如果不是,使用它的理由是什么?

c++ templates polymorphism
1个回答
0
投票

在 C++20 之前,这就是我们所拥有的一切。您无法从 C++20 之前的 C++ 模板中夺走的一件事是,它们允许极大的灵活性(在某些情况下可能需要),并且在某种程度上允许 API 提供者和 API 使用者之间的隐式契约。

C++20 出现并引入了概念,几乎从字面上看是为了解决由于所述合同过于宽松而引起的问题。

现在,该函数可能会写成:

template <class Container>
concept DrawableContainer = requires (Container c) {
  { c.begin() };
  { c.end() };
  { *(c.begin()) } -> std::convertible_to<typename Container::value_type>;
  requires std::invocable<decltype(&Shape::draw), decltype(*(c.begin()))>;
  // Plus whatever else constraints are needed
};

void draw_all(DrawableContainer auto& c)
{
    for_each(c.begin(),c.end(),mem_fun(&Shape::draw));
}

这仍然允许相同的灵活性,但具有即使仅使用代码也可以更好地记录的附加功能。

如果您无法了解概念,那么没有比好的旧模板更好的解决方案了。您可以尝试在任何地方使用SFINAE,以使其更容易使用。

© www.soinside.com 2019 - 2024. All rights reserved.