Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ CRTP:我能';即使使用静态多态性,也无法消除重复代码_C++_Templates_Static_Crtp - Fatal编程技术网

C++ CRTP:我能';即使使用静态多态性,也无法消除重复代码

C++ CRTP:我能';即使使用静态多态性,也无法消除重复代码,c++,templates,static,crtp,C++,Templates,Static,Crtp,1。问题描述 我有两个类Derived1和Derived2。所有函数都是相同的,其中大多数包含大约100行唯一的区别是正在操纵的静态对象Derived1正在操作p1和Derived2正在操作p2。这两个类都使用静态函数。但是有一个约束,被操纵的对象只能在包内使用。文件的结构如下所示: /** * * include/derived.hpp * include/derived1.hpp * include/derived2.hpp * * src/point.hpp * src/

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。问题

我不知道静态多态性如何解决我的问题。我如何才能像一样拥有一个公共函数
create
,该函数知道我正在操作哪个静态实例,比如
p1
p2
,同时考虑到我前面提到的约束:正在操作的对象只能在包内使用。


3。源代码C++ 11(我不能使用较新版本)>/P> 源代码基于以下文章

#包括
#包括
#包括
使用名称空间std;
结构点{
std::向量点;
};
静态点p1;
静态点p2;
模板<派生类>
阶级基础{
公众:
静态void create(){
派生::创建();
}
静态无效替换(){
派生::替换();
}
静态无效清除(){
派生::clear();
}
};
类Derived1:公共基{
好友类基类;
私人:
静态void create(){
p1.点={1,2,3,4,5,6,7,8,9};
}
静态无效替换(){
std::replace_if(p1.points.begin(),p1.points.end(),[](int x){return x>4;},5);
//100多行
}
静态无效清除(){
p1.points.clear();
}
};
类Derived2:公共基{
好友类基类;
私人:
静态void create(){
p2.点={1,2,3,4,5,6,7,8,9};
}
静态无效替换(){
std::replace_if(p2.points.begin(),p2.points.end(),[](int x){return x>4;},5);
//100多行与导出1相同
}
静态无效清除(){
p2.points.clear();
}
};
int main()
{
Base::create();
Base::create();
Base::replace();
Base::replace();
Base::clear();
Base::clear();
返回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;
}

#包括
#包括
#包括
使用名称空间std;
结构点{
std::向量点;
};
//隐藏点
类封装{
模板
C类{
公众:
静态void create(){
p、 点={1,2,3,4,5,6,7,8,9};
}
静态无效替换(){
std::如果需要,请更换(
p、 points.begin(),p.points.end(),[](int x){return x>4;},5);
//100多行与导出1相同
}
静态无效清除(){
p、 点。清除();
}
};
静态点p1;
静态点p2;
公众:
使用C1=C;
使用C2=C;
};
//需要定义它们,或者使用上面的C++17内联关键字
点封装::p1;
点封装::p2;
使用C1=封装::C1;
使用C2=封装::C2;
//你仍然可以做到,但这基本上总是可能的。
模板
结构提取点;
模板
结构提取点{
静态点&点;
};
模板
点&提取点::点=p;
int main(){
C1::create();
C2::create();
C1::replace();
C2::replace();
C1::clear();
C2::clear();
自动&p1=提取点::点;
返回0;
}

这适用于所有静态
s(基本上,地址必须在编译tiem时知道才能工作)。间接寻址也没有运行时开销,因为编译器知道编译时引用的是什么。

我不确定是否可以使用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;
}

#包括
#包括
#包括
使用名称空间std;
结构点{
std::向量点;
};
//隐藏点
类封装{
模板
C类{
公众:
静态void create(){
p、 点={1,2,3,4,5,6,7,8,9};
}
静态无效替换(){
std::如果需要,请更换(
p、 points.begin(),p.points.end(),[](int x){return x>4;},5);
//100多行与导出1相同
}
静态无效清除(){
p、 点。清除();
}
};
静态点p1;
静态点p2;
公众:
使用C1=C;
使用C2=C;
};
//需要定义它们,或者使用上面的C++17内联关键字
点封装::p1;
点封装::p2;
使用C1=封装::C1;
使用C2=封装::C2;
//你仍然可以做到,但这基本上总是可能的。
模板
结构提取点;
模板
结构提取点{
静态点&点;
};
模板
点&提取点::点=p;
int main(){
C1::create();
C2::create();
C1::replace();
C2::replace();
C1::clear();
C2::clear();
自动&p1=提取点::点;
返回0;
}

这适用于所有静态
s(基本上,地址必须在编译tiem时知道才能工作)。间接寻址也没有运行时开销,因为编译器知道编译时引用的是什么。

你不能有一个
静态DerivedX::Point&p=pX
,然后在
Base
中使用
p
?对于此类问题,您使用了错误的设计。这应该在派生类不共享代码时使用,