C++ 如何在C+中允许成员函数的自定义返回类型进行类型擦除+;?

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

在过去的几年中,类型擦除或基于概念的运行时多态性变得非常流行,参见Sean Parent的演讲,或resp。由、或执行

下面是Sean Parent演讲中的一个例子:

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*);