【发布时间】:2021-12-17 00:52:24
【问题描述】:
我观看了 Klaus Iglberger 在 CppCon 2021 上关于类型擦除的精彩演讲。我根据他的示例自己设置了模式。他的 External Polymorphic 片段被分派给外部类的友元函数。那篇文章不适合我。
我尝试过改变定义的顺序并将友元函数的实现拉到类之外。我还没有设置实现文件,因为我不太相信这会是一个解决方案。
我使用的是 GCC 9.3 和 Clang 10。错误看起来一样。铿锵10:
type_erasure_example.cpp:57:22: error: too many arguments to function call, expected 0, have 1 serialize( object );
type_erasure_example.cpp:61:28: error: too many arguments to function call, expected 2, have 3 draw( object, x, y );
GCC9.3:
type_erasure_example.cpp:57:11: error: no matching function for call to ‘Shape::ShapeModel<Square>::serialize(const Square&) const’ 57 | serialize( object );
type_erasure_example.cpp:61:11: error: no matching function for call to ‘Shape::ShapeModel<Square>::draw(const Square&, int&, int&) const’ 61 | draw( object, x, y );
#include <iostream>
#include <memory>
#include <vector>
class Circle
{
public:
explicit Circle( double rad )
: radius{ rad }
// ... Remaining data members
{}
double getRadius() const noexcept { return radius; }
// ... getCenter(), getRotation(), ...
private:
double radius;
// ... Remaining data members
};
class Square
{
public:
explicit Square( double s )
: side{ s }
// ... Remaining data members
{}
double getSide() const noexcept { return side; }
// ... getCenter(), getRotation(), ...
private:
double side;
// ... Remaining data members
};
class Shape
{
private:
struct ShapeConcept
{
virtual ~ShapeConcept() {}
virtual void serialize() const = 0;
virtual void draw(int x, int y) const = 0;
virtual std::unique_ptr<ShapeConcept> clone() const = 0;
};
template< typename T >
struct ShapeModel : ShapeConcept
{
ShapeModel( T&& value )
: object{ std::forward<T>(value) }
{}
std::unique_ptr<ShapeConcept> clone() const override
{
return std::make_unique<ShapeModel>(*this);
}
void serialize() const override
{
serialize( object ); // Error
}
void draw( int x, int y ) const override
{
draw( object, x, y ); // Error
}
T object;
};
friend void serialize( Shape const& shape )
{
shape.pimpl->serialize();
}
friend void draw( Shape const& shape, int x, int y )
{
shape.pimpl->draw( x, y );
}
std::unique_ptr<ShapeConcept> pimpl;
public:
template< typename T >
Shape( T&& x )
: pimpl{ new ShapeModel<T>( std::forward<T>(x) ) }
{}
// Special member functions
Shape( Shape const& s );
Shape( Shape&& s );
Shape& operator=( Shape const& s );
Shape& operator=( Shape&& s );
};
void serialize( Circle const& circle ) {
std::cout << "Serializing a circle with radius "
<< circle.getRadius() << std::endl;
}
void draw( Circle const& circle, int x, int y ) {
std::cout << "Drawing a circle with radius "
<< circle.getRadius() << " Coordinates ("
<< x << ", " << y << ")" << std::endl;
}
void serialize( Square const& square ) {
std::cout << "Serializing a square with side "
<< square.getSide() << std::endl;
}
void draw( Square const& square, int x, int y ) {
std::cout << "Drawing a square with side "
<< square.getSide() << " Coordinates ("
<< x << ", " << y << ")" << std::endl;
}
void drawAllShapes( std::vector<Shape> const& shapes )
{
for( auto const& shape : shapes )
{
draw( shape , 0.0, 0.0 );
}
}
int main()
{
using Shapes = std::vector<Shape>;
// Creating some shapes
Shapes shapes;
shapes.emplace_back( Circle{ 2.0 } );
shapes.emplace_back( Square{ 1.5 } );
shapes.emplace_back( Circle{ 4.2 } );
// Drawing all shapes
drawAllShapes( shapes );
}
【问题讨论】:
-
请将 full 和 complete 错误输出复制粘贴到您的问题中。并在出现错误的代码中添加 cmets。
-
与look-up rule,
void serialize() const override { serialize( object );}只创建类的成员(ADL生效前)。 -
如果您想看另一个示例,因为它有点令人兴奋,您可能需要查看我的答案:stackoverflow.com/a/63743699/4641116。 (我通过将名称更改为
fwd_serialize让你的代码工作,而你通过::serialize让它工作。) -
@Jarod42 为什么查找会停止呢?是不是因为查找集一旦找到
ShapeModel::serializa()就不是空的,即使签名不匹配? -
ADL 还声明 “首先,如果通常的非限定查找生成的查找集包含以下任何内容,则不考虑依赖于参数的查找:1) 类成员的声明".
标签: c++ type-erasure argument-dependent-lookup friend-function