摘要
有没有办法在模板化类型上调用类方法,该模板可能是指针或引用而不知道哪个而不是获取编译器/链接器错误?
细节
我有一个模板化的QuadTree实现,可以采用以下任何非平凡的用户定义类型:
//Abstract Base Class
a2de::Shape
//Derived Classes
a2de::Point
a2de::Line
a2de::Rectangle
a2de::Circle
a2de::Ellipse
a2de::Triangle
a2de::Arc
a2de::Spline
a2de::Sector
a2de::Polygon
Run Code Online (Sandbox Code Playgroud)
但它们可能是指针或引用,因为它们都是从a2de :: Shape派生的.因此专业化被声明为:
template class QuadTree<a2de::Shape&>;
//...similar for all derived types as references.
template class QuadTree<a2de::Shape*>;
//...similar for all derived types as pointers
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是当间接(或缺少)未知时调用类方法的能力,并且由于模板,生成了两组代码:
template<typename T>
bool QuadTree<T>::Add(T& elem) {
//When elem of type T is expecting a pointer here
//-> notation fails to compile where T is a reference i.e.:
//template class QuadTree<a2de::Shape&>
//with "pointer to reference is illegal" …Run Code Online (Sandbox Code Playgroud) 假设我想编写一个接收指针的函数.但是我想允许调用者使用裸指针或智能指针 - 无论他们喜欢什么.这应该是好的,因为我的代码应该依赖于指针语义,而不是指针实际实现的方式.这是一种方法:
template<typename MyPtr>
void doSomething(MyPtr p)
{
//store pointer for later use
this->var1 = p;
//do something here
}
Run Code Online (Sandbox Code Playgroud)
上面将使用duck typing并且可以传递裸指针或智能指针.当传递的值是基指针时我们需要查看是否可以转换为派生类型.
template<typename BasePtr, typename DerivedPtr>
void doSomething(BasePtr b)
{
auto d = dynamic_cast<DerivedPtr>(b);
if (d) {
this->var1 = d;
//do some more things here
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码适用于原始指针,但不适用于智能指针,因为我需要使用dynamic_pointer_cast而不是dynamic_cast.
上面问题的一个解决方案是我添加了一个新的实用工具方法,类似于universal_dynamic_cast通过选择使用的重载版本在原始指针和智能指针上工作std::enable_if.
我的问题是,
shared_ptr在我们的库公共API中使用?我知道这取决于库的目的,但是使用shared_ptr所有API签名的一般感觉是什么?假设我们只需要支持C++ 11.shared_ptr<MyBase>会牺牲灵活性来让调用者传递包含在任何指针中的任何东西,但是我的代码的读者会更自信,并且可以在应该进入的内容上构建更好的模型.在C++公共库API中,是否有这样或那样的一般偏好/优势?template<typename T>并让调用者决定T是否是某种指针类型或引用或类.如果我必须在T中调用某些东西,这种超级泛型方法显然不起作用,因为C++需要解除引用指针类型,这意味着我必须创建实用程序方法,例如universal_deref使用std::enable_if将*运算符应用于指针类型但不对普通对象执行任何操作.我想知道是否有任何设计模式可以更容易地实现这种超级通用方法.最重要的是,是否值得去解决所有这些问题,或者只是保持简单并 …假设我有这两个std::vector:
std::vector<int> v_int(1000);
std::vector<T> v_T(1000); // Where T is copy-costy type
Run Code Online (Sandbox Code Playgroud)
如果我需要循环浏览它们(不需要)而不需要编辑我可能使用的项目:
for(const auto item:v_int){
//...
}
for(const auto& item:v_T){ //Note &
//...
}
Run Code Online (Sandbox Code Playgroud)
迭代使用const auto item:v_T太糟糕了,因为每次迭代都会执行一次复制.然而,使用const auto& item:v_int不是最佳但不是那么糟糕.因此,如果我需要一个处理它们的代码我曾经使用过const auto& item:v.
问题:是否有一种通用的方法来编写将为它们使用最佳声明的for循环?就像是:
template <typename T>
void iterate(const std::vector<T> v){
for(const auto/*&*/ item:v){ // activate & if T is not elementary type
//...
}
}
Run Code Online (Sandbox Code Playgroud)