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应该是一个基类
#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.