【问题标题】:C++ detect if a type can be called with a template typeC ++检测是否可以使用模板类型调用类型
【发布时间】:2022-01-01 12:17:42
【问题描述】:

我正在开发一个程序,其中一些数据是静态分配的,而一些是动态分配的。现在我想要另一种类型,可以使用该类型的任何模板作为其参数来调用。

#include <array>
#include <vector>
template <int size> class Foo {
  std::array<int, size> data;
public:
  int& operator[](std::size_t idx) {return data[idx];}
};
template <> class Foo<-1> {
  std::vector<int> data;
public:
  int& operator[](std::size_t idx) {return data[idx];}
};
// option 1- polymorphism
struct FooCaller {
  virtual void operator()(Foo data) = 0; // how would I make this work with both forms of Foo?
};
// option 2- generic programming
template <class T> concept CanCallFoo = requires (const T& t) {
  t(std::declval<Foo&>()); // how do I ensure that this can call any overload of Foo?
};

这两种方法都可以,但我不知道该怎么做。因为完整的代码更复杂,我宁愿不要让两个 Foos 都从一个基类继承。

【问题讨论】:

  • 看看std::span,它对已知大小和运行时大小做了类似的事情。
  • struct FooCaller { template&lt;int _S&gt; void operator()(Foo&lt;_S&gt; data){...} } 适合你吗?
  • @Lux 命名 _S 将导致未定义的行为。
  • @JDługosz 啊,谢谢你抓住了我!不幸的是,我似乎无法再编辑该评论,但对于任何想知道为什么它是 UB 的人,在 C++ 中,以___[capital letter] (以及其他)开头的标识符被保留(通常用于编译器或stdlib),因此,如果您使用它们,可能会出现一些不稳定的行为。有关更多信息,请参阅here(部分:“声明中”)!

标签: c++ templates sfinae


【解决方案1】:

可调用的F 可以编写一个可以被Foo&lt;x&gt; 调用的限制,这样x 的任意函数必须为真才有效。

为了让您的“可以使用任何Foo 调用”测试正常工作,您必须在编译时反转任意函数。

除了检查x 的所有 2^32 个可能值之外,没有实用的方法可以做到这一点。不完全是。您遇到的问题是 F 类型可能过于强大,您无法确定其属性。这与 Halt 和 Rice 定理以及模板元编程和 C++ 重载解析是图灵完备的事实有关(仅相关,因为 2^32 是有限的)。

在另一种情况下,您可以键入擦除。编写一个类型RefAnyFoo/AnyFooValue,它可以从任何Foo 类型构造并“类型擦除”您想要的操作,就像std::function&lt;void(int)&gt; 类型如何擦除一样。它既可以直接输入Foo,也可以实际限制为从模板生成的类型的实例。

那么您的界面就是一个带有AnyFooValue/RefAnyFoo 的界面(取决于您是在谈论副本还是引用)。

现在,把它翻过来,你可以写一个接受F 的概念,它接受RefFooAny。这不是您所要求的,但您有可能遇到 X/Y 问题;您遇到了一个真正的问题,提出了不完整的解决方案,然后询问如何让您的解决方案发挥作用,而不是原来的问题。

同样,您可能只关心Foo&lt;?&gt; 的某些ducktype 属性而不关心特定类型。然后,您的可调用对象可以使用检查这些鸭子类型的概念;这同样不能解决您的问题,因为它会颠倒过来,因为您无法验证可调用对象是否接受来自可调用对象之外的整个概念。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-13
    相关资源
    最近更新 更多