CRTP:即使使用静态多态性,我也无法摆脱重复代码
CRTP: I can't get rid of duplicate code even with static polymorphism
1.问题描述
我有两个 类 Derived1
和 Derived2
。所有函数都是相同的,其中大部分包含大约 100 行。 唯一的区别 是被操作的静态对象。 Derived1
在操纵p1
,Derived2
在操纵p2
。 类 都使用静态函数。但是有一个约束,被操作的对象只能在包内部使用。文件结构如下:
/**
*
* include/derived.hpp
* include/derived1.hpp
* include/derived2.hpp
*
* src/point.hpp
* src/derived.cpp
* src/Derived1.cpp
* src/derived2.cpp
*
* Point is only visible in the package
* */
2。问题
我看不出静态多态性如何解决我的问题。我怎样才能像 common 函数 create
那样知道我正在操纵哪个静态实例,比如 p1
或 p2
同时考虑到约束我之前声明过:被操作的对象只能在包内使用。
3。源代码 c++ 11(我不能使用较新的版本)
源码参考以下文章Static Polymorphism in C++.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Point{
std::vector<int> points;
};
static Point p1;
static Point p2;
template< class Derived >
class Base {
public:
static void create() {
Derived::create();
}
static void replace() {
Derived::replace();
}
static void clear() {
Derived::clear();
}
};
class Derived1: public Base< Derived1 > {
friend class Base< Derived1 >;
private:
static void create() {
p1.points = {1,2,3,4,5,6,7,8,9};
}
static void replace() {
std::replace_if(p1.points.begin(), p1.points.end(), [](int x){return x > 4;}, 5);
//100 more lines
}
static void clear() {
p1.points.clear();
}
};
class Derived2: public Base< Derived2 > {
friend class Base< Derived2 >;
private:
static void create() {
p2.points = {1,2,3,4,5,6,7,8,9};
}
static void replace() {
std::replace_if(p2.points.begin(), p2.points.end(), [](int x){return x > 4;}, 5);
//100 more lines same as derived 1
}
static void clear() {
p2.points.clear();
}
};
int main()
{
Base< Derived1 >::create();
Base< Derived2 >::create();
Base< Derived1 >::replace();
Base< Derived2 >::replace();
Base< Derived1 >::clear();
Base< Derived2 >::clear();
return 0;
}
我不确定你是否可以让它与 CRTP 一起工作,但使用非类型模板参数很容易:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Point {
std::vector<int> points;
};
// Hides the points
class Encapsulate {
template<Point &p>
class C {
public:
static void create() {
p.points = {1, 2, 3, 4, 5, 6, 7, 8, 9};
}
static void replace() {
std::replace_if(
p.points.begin(), p.points.end(), [](int x) { return x > 4; }, 5);
// 100 more lines same as derived 1
}
static void clear() {
p.points.clear();
}
};
static Point p1;
static Point p2;
public:
using C1 = C<p1>;
using C2 = C<p2>;
};
// Need to define them out-of-line or use C++17 inline keyword above
Point Encapsulate::p1;
Point Encapsulate::p2;
using C1 = Encapsulate::C1;
using C2 = Encapsulate::C2;
// You can still get to it, but that is basically always possible.
template<class T>
struct extract_point;
template<template<Point &> class T, Point &p>
struct extract_point<T<p>> {
static Point &point;
};
template<template<Point &> class T, Point &p>
Point &extract_point<T<p>>::point = p;
int main() {
C1::create();
C2::create();
C1::replace();
C2::replace();
C1::clear();
C2::clear();
auto &p1 = extract_point<C1>::point;
return 0;
}
这适用于所有静态 Point
s(基本上,地址必须在编译时已知才能起作用)。间接也没有运行时开销,因为编译器知道 p
在编译时引用什么。
1.问题描述
我有两个 类 Derived1
和 Derived2
。所有函数都是相同的,其中大部分包含大约 100 行。 唯一的区别 是被操作的静态对象。 Derived1
在操纵p1
,Derived2
在操纵p2
。 类 都使用静态函数。但是有一个约束,被操作的对象只能在包内部使用。文件结构如下:
/**
*
* include/derived.hpp
* include/derived1.hpp
* include/derived2.hpp
*
* src/point.hpp
* src/derived.cpp
* src/Derived1.cpp
* src/derived2.cpp
*
* Point is only visible in the package
* */
2。问题
我看不出静态多态性如何解决我的问题。我怎样才能像 common 函数 create
那样知道我正在操纵哪个静态实例,比如 p1
或 p2
同时考虑到约束我之前声明过:被操作的对象只能在包内使用。
3。源代码 c++ 11(我不能使用较新的版本)
源码参考以下文章Static Polymorphism in C++.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Point{
std::vector<int> points;
};
static Point p1;
static Point p2;
template< class Derived >
class Base {
public:
static void create() {
Derived::create();
}
static void replace() {
Derived::replace();
}
static void clear() {
Derived::clear();
}
};
class Derived1: public Base< Derived1 > {
friend class Base< Derived1 >;
private:
static void create() {
p1.points = {1,2,3,4,5,6,7,8,9};
}
static void replace() {
std::replace_if(p1.points.begin(), p1.points.end(), [](int x){return x > 4;}, 5);
//100 more lines
}
static void clear() {
p1.points.clear();
}
};
class Derived2: public Base< Derived2 > {
friend class Base< Derived2 >;
private:
static void create() {
p2.points = {1,2,3,4,5,6,7,8,9};
}
static void replace() {
std::replace_if(p2.points.begin(), p2.points.end(), [](int x){return x > 4;}, 5);
//100 more lines same as derived 1
}
static void clear() {
p2.points.clear();
}
};
int main()
{
Base< Derived1 >::create();
Base< Derived2 >::create();
Base< Derived1 >::replace();
Base< Derived2 >::replace();
Base< Derived1 >::clear();
Base< Derived2 >::clear();
return 0;
}
我不确定你是否可以让它与 CRTP 一起工作,但使用非类型模板参数很容易:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Point {
std::vector<int> points;
};
// Hides the points
class Encapsulate {
template<Point &p>
class C {
public:
static void create() {
p.points = {1, 2, 3, 4, 5, 6, 7, 8, 9};
}
static void replace() {
std::replace_if(
p.points.begin(), p.points.end(), [](int x) { return x > 4; }, 5);
// 100 more lines same as derived 1
}
static void clear() {
p.points.clear();
}
};
static Point p1;
static Point p2;
public:
using C1 = C<p1>;
using C2 = C<p2>;
};
// Need to define them out-of-line or use C++17 inline keyword above
Point Encapsulate::p1;
Point Encapsulate::p2;
using C1 = Encapsulate::C1;
using C2 = Encapsulate::C2;
// You can still get to it, but that is basically always possible.
template<class T>
struct extract_point;
template<template<Point &> class T, Point &p>
struct extract_point<T<p>> {
static Point &point;
};
template<template<Point &> class T, Point &p>
Point &extract_point<T<p>>::point = p;
int main() {
C1::create();
C2::create();
C1::replace();
C2::replace();
C1::clear();
C2::clear();
auto &p1 = extract_point<C1>::point;
return 0;
}
这适用于所有静态 Point
s(基本上,地址必须在编译时已知才能起作用)。间接也没有运行时开销,因为编译器知道 p
在编译时引用什么。