Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/135.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

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++ C+中是否有设计模式+;是否有助于使用统一的功能接口查询不同类型的数据?_C++_Templates_Design Patterns - Fatal编程技术网

C++ C+中是否有设计模式+;是否有助于使用统一的功能接口查询不同类型的数据?

C++ C+中是否有设计模式+;是否有助于使用统一的功能接口查询不同类型的数据?,c++,templates,design-patterns,C++,Templates,Design Patterns,我想提供一个函数声明/定义,它根据输入参数返回正确类型的数据。这听起来很像函数模板的用途,但更具体地说,我希望函数界面看起来像: template<class InT> RetT getData(InT*); 模板 RetT getData(InT*); 在哪里, 要求1:RetT取决于输入类型InT,不一定等于InT 要求2:此外,我想为所有实际的InT类型强制执行一个公共接口,以确定什么是RetT。换句话说,希望,InT应该是一个基类 关于后台应用程序。假设我有一个文本处

我想提供一个函数声明/定义,它根据输入参数返回正确类型的数据。这听起来很像函数模板的用途,但更具体地说,我希望函数界面看起来像:

template<class InT>
RetT getData(InT*);
模板
RetT getData(InT*);
在哪里,

  • 要求1:RetT取决于输入类型InT,不一定等于InT
  • 要求2:此外,我想为所有实际的InT类型强制执行一个公共接口,以确定什么是RetT。换句话说,希望,InT应该是一个基类
关于后台应用程序。假设我有一个文本处理系统,我可以为它指定各种配置。有些配置可能是标志(即布尔值),如performCompact、addSpacing等。有些配置可能是标记(即字符串文字),如prefixToPath、surfixToLastName等。有些配置可能是自定义数据类型,如textColorMap、fontFamily等

我想提供一个通用函数来查询每个配置的数据,而不是每个配置一个函数。由于配置数据存储在不同的类型中,因此我需要此函数根据用于查询的配置返回正确类型的数据

选择此设计的主要原因是为了节省维护工作量。这个查询基础设施位于其自己的组件中,不同的团队在其自己的组件中处理不同的配置子集。我希望尽量减少维护工作量,以便在添加新配置时,无需修改查询接口

下面给出了一些示例代码。这满足了这两个要求,但是我仍然想知道是否有一种方法可以避免使用Requirement2的类模板

#include <iostream>
using namespace std;

// In a *.hpp file in component A
template<class T>
auto getData(T* spec) {
    return spec->data();
}

template<class DataT>
class Configuration {
    public:
    virtual DataT data() = 0; 
};

// In some other components source files
class PerformCompact : Configuration<bool> {
    private:
    bool _data;
    public:
    PerformCompact(bool d):_data(d){}
    bool data() override {return _data;}

};

class PrefixToPath : Configuration<string>{
    private:
    string _data;
    public:
    PrefixToPath(string d):_data(d){}
    string data() override {return _data;}
};

// In one application source file
int main()
{
   PerformCompact performCompact(true);
   PrefixToPath prefixToPath("Some string");
   auto pd = getData(&performCompact);
   auto pstr = getData(&prefixToPath);
   cout << pd << endl;
   cout << pstr << endl;

   return 0;
}
#包括
使用名称空间std;
//在组件a中的*.hpp文件中
模板
自动获取数据(T*规格){
返回规格->数据();
}
模板
类配置{
公众:
虚拟数据t data()=0;
};
//在其他一些组件源文件中
类PerformCompact:Configuration{
私人:
布尔数据;
公众:
性能比较(bool d):_data(d){}
bool data()重写{return\u data;}
};
类PrefixToPath:配置{
私人:
字符串数据;
公众:
PrefixToPath(字符串d):_data(d){}
字符串数据()重写{return\u data;}
};
//在一个应用程序源文件中
int main()
{
PerformCompact PerformCompact(真);
PrefixToPath PrefixToPath(“某些字符串”);
自动pd=获取数据(&performCompact);
自动pstr=getData(&prefixToPath);

cout您可以为
InT
定义一个公共需求,以明确定义返回类型,例如:

class PerformCompact : Configuration<bool> {
    typedef bool DataReturnType;
    ...
}
如果希望避免显式定义类型,则在C++17中,可以让编译器使用
auto
关键字自行推断类型:

template<class T>
auto getData(T* spec) {
    return spec->data();
}
模板
自动获取数据(T*规格){
返回规格->数据();
}

可以将SFINAE与
中的新元函数一起使用,检查函数返回行中类型的条件。如果某些函数模板的条件失败,而其他函数模板的条件没有失败,SFINAE将确保编译器继续运行并选择最佳候选函数模板

如果可以在编译时检查类型上的条件,这当然有效。这个小示例检查两个类型是否可相互分配,然后启用返回类型。如果类型不可分配(C与(a,B)的组合),则编译失败:

#include <type_traits>
#include <cassert>

class A; 
class B; 
class C; 

class A 
{
    public: 
        void operator=(B const& b) {}; 
};  

class B 
{
    public: 
        void operator=(A const& a) {}; 
}; 

class C {}; 

template<class RetT, class InT>
std::enable_if_t
<
    std::is_assignable<InT,RetT>::value, 
    RetT
>
getData(InT*)
{
    RetT result; 

    return result;
};

using namespace std; 

int main()
{
    A* Aptr = new A;
    B* Bptr = new B;
    C* Cptr = new C;

    getData<A>(Bptr); 
    getData<B>(Aptr); 


    // Assignments not there, so the compilation fails. 
    getData<B>(Cptr); 
    getData<C>(Bptr); 
    getData<A>(Cptr); 
    getData<C>(Aptr); 

    delete Aptr; 
    Aptr = nullptr;
    delete Bptr; 
    Bptr = nullptr; 
    delete Cptr; 
    Cptr = nullptr;

    return 0;
};
如果在编译时计算constexpr
,并且如果为true

   RetT result; 

   return result;
,否则将编译assert语句。如果尝试将函数与C、(A,B)组合使用,则会出现运行时错误:

 RetT getData(InT*) [with RetT = B; InT = C]: Assertion `false && "RetT and IntT not assignable."' failed.

如果希望在编译时激活断言,可以使用
static\u assert

我看不出基本
Configuration
类的任何原因。全局
getData
将适用于具有
data
函数的任何对象。您可以将SFINAE添加到模板中,使其仅适用于函数如果你真的想要的话,它有一个
data
成员。
template<class RetT, class InT>
RetT
getData(InT*)
{
    if constexpr (std::is_assignable<InT,RetT>::value)
    {
        RetT result; 

        return result;
    }
    else assert(false && "RetT and IntT not assignable.");
};
   RetT result; 

   return result;
 RetT getData(InT*) [with RetT = B; InT = C]: Assertion `false && "RetT and IntT not assignable."' failed.