C++ 如何在C+中允许成员函数的自定义返回类型进行类型擦除+;?
在过去的几年中,类型擦除或基于概念的运行时多态性变得非常流行,参见Sean Parent的演讲,或resp。由、或执行 下面是Sean Parent演讲中的一个例子:C++ 如何在C+中允许成员函数的自定义返回类型进行类型擦除+;?,c++,type-erasure,C++,Type Erasure,在过去的几年中,类型擦除或基于概念的运行时多态性变得非常流行,参见Sean Parent的演讲,或resp。由、或执行 下面是Sean Parent演讲中的一个例子: class object_t { struct concept_t { virtual ~concept_t() = default; virtual void draw_(ostream&, size_t) const = 0; }; template <ty
class object_t {
struct concept_t {
virtual ~concept_t() = default;
virtual void draw_(ostream&, size_t) const = 0;
};
template <typename T>
struct model final : concept_t {
model(T x) : data_(move(x)) { }
void draw_(ostream& out, size_t position) const override
{ draw(data_, out, position); }
T data_;
};
shared_ptr<const concept_t> self_;
public:
template <typename T>
object_t(T x) : self_(make_shared<model<T>>(move(x))){ }
friend void draw(const object_t& x, ostream& out, size_t position)
{ x.self_->draw_(out, position); }
};
这对于任何T
都很容易实现,因为返回类型是void
,并且参数签名在编译时都是已知的。如果返回类型为int、double、std::string等,则也是如此
下面是实际问题:如何为自定义返回类型RType
resp执行此操作。参数类型ArgType
编辑:
最终目标是有两个班
class MyClass {
using ArgType = /* e.g. int*/;
using RType = /* e.g. double*/;
RType foo (ArgType arg) const {/*...*/;}
};
及
这样我们就可以将两者都用于对象
,即
object_t myObj(MyClass(/*...*/));
object_t yourObj(YourClass(/*...*/));
// use provided functionality
// ... myObj.foo(...)
// ... yourObj.foo(...)
当然,
object\u t::foo
的任何一个重载都必须有一个返回类型,这是有充分理由的:如果客户机可以接收一个类型的对象,而该类型的对象只存在于创建object\u t
的其他翻译单元中,那么编译器怎么可能生成代码来处理它呢?如果有某个类型可以将所有不同的返回类型转换为,您可以将其用作外部返回类型,但这肯定太有限了
当然,您可以提供一个至少接受任何类型的foo
函数模板,但是您将如何实现它呢?函数模板不能是虚拟的,原因类似于(典型)vtable的大小不能从任何一个翻译单元中得知。您可以将几种已知类型中的每一种路由到它自己的虚拟函数,但是必须事先知道这些函数的列表;或者,您可以再次依赖于将任何参数转换为某种已知类型,但模板的客户机可以自己完成
唯一的另一种选择是为参数和返回值定义一个接口,以提供并针对它编写所有实现类和客户机代码。这当然是许多脚本语言的工作方式:本质上,CPython中的每个内置函数都有签名
PyObject* func(PyObject*);
因此,即使是任意Python数据的有状态C++可访问操纵器也可以存储在
std::function
中,而无需定义自己的类型擦除类。这里不清楚您的意思。您想让对象\u t::draw
根据给定的参数返回不同的值吗?您希望给予对象的每个T
都能够获取任何ArgType
,还是希望每个T
都能够将特定的ArgType
映射到特定的RType
?如果是后者,您希望object\u t
成为ArgType
上的模板,还是希望object\u t::draw
强制包含的对象能够获取任何ArgType
?您不能不使用(ii),或者使用协变返回类型规则提供的灵活性。@FrançoisAndrieux抱歉,我不清楚这一点。“现在,任何版本都可以。”尼古拉斯我编辑了这个问题。我希望问题现在已经清楚了。
class MyClass {
using ArgType = /* e.g. int*/;
using RType = /* e.g. double*/;
RType foo (ArgType arg) const {/*...*/;}
};
class YourClass {
using ArgType = /* e.g. size_t*/;
using RType = /* e.g. float*/;
RType foo (ArgType arg) const {/*...*/;}
};
object_t myObj(MyClass(/*...*/));
object_t yourObj(YourClass(/*...*/));
// use provided functionality
// ... myObj.foo(...)
// ... yourObj.foo(...)
PyObject* func(PyObject*);