sdg*_*sdh 11 c++ templates pointers
我的真实例子非常大,所以我将使用简化的例子.假设我有一个矩形的数据类型:
struct Rectangle {
int width;
int height;
int computeArea() {
return width * height;
}
}
Run Code Online (Sandbox Code Playgroud)
另一种消耗该类型的类型,例如:
struct TwoRectangles {
Rectangle a;
Rectangle b;
int computeArea() {
// Ignore case where they overlap for the sake of argument!
return a.computeArea() + b.computeArea();
}
};
Run Code Online (Sandbox Code Playgroud)
现在,我不想对用户的所有权限制TwoRectangles,所以我想把它作为一个模板:
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
// Ignore case where they overlap for the sake of argument!
return a.computeArea() + b.computeArea();
}
};
Run Code Online (Sandbox Code Playgroud)
用途:
TwoRectangles<Rectangle> x;
TwoRectangles<Rectangle*> y;
TwoRectangles<std::shared_ptr<Rectangle>> z;
// etc...
Run Code Online (Sandbox Code Playgroud)
问题是如果调用者想要使用指针,函数的主体应该是不同的:
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
assert(a && b);
return a->computeArea() + b->computeArea();
}
};
Run Code Online (Sandbox Code Playgroud)
统一我的模板化函数的最佳方法是什么,以便最大量的代码重用于指针,值和智能指针?
Bar*_*rry 22
执行此操作的一种方法是将所有内容封装在内TwoRectangles,如下所示:
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
return areaOf(a) + areaOf(b);
}
private:
template <class U>
auto areaOf(U& v) -> decltype(v->computeArea()) {
return v->computeArea();
}
template <class U>
auto areaOf(U& v) -> decltype(v.computeArea()) {
return v.computeArea();
}
};
Run Code Online (Sandbox Code Playgroud)
您不太可能拥有这两个表达式都有效的类型.但是你总是可以用第二个参数添加额外的消歧areaOf().
另一种方法是利用以下事实:在标准库中已经有一种方法可以调用函数:std::invoke().您只需要知道基础类型:
template <class T, class = void>
struct element_type {
using type = T;
};
template <class T>
struct element_type<T, void_t<typename std::pointer_traits<T>::element_type>> {
using type = typename std::pointer_traits<T>::element_type;
};
template <class T>
using element_type_t = typename element_type<T>::type;
Run Code Online (Sandbox Code Playgroud)
和
template<typename T>
struct TwoRectangles {
T a;
T b;
int computeArea() {
using U = element_type_t<T>;
return std::invoke(&U::computeArea, a) +
std::invoke(&U::computeArea, b);
}
};
Run Code Online (Sandbox Code Playgroud)