在C++中创建"template"对象的机制
Mechanism to create "template" objects in C++
我希望能够用一些默认值初始化对象,但要从外部代码(不嵌入类本身(来实现这一点。对象暴露在外部编辑器中,我不想一次又一次地设置相同的值,只更改一些不同的值。由于我已经有了模板类,所以我想从"traits"类中完成这项工作。
这是我想要实现的一个简单的例子:
template<typename Traits>
class Test
{
public:
Test()
{
//if Traits has Init init function call Traits::Init(this)
}
private:
typename Traits::Type value;
friend Traits;
};
struct TestTraits
{
typedef std::string Type;
};
struct TestTraitsInit
{
typedef int Type;
static void Init(Test<TestTraitsInit>* obj)
{
obj->value = 0;
}
};
int main()
{
Test<TestTraits> obj1;
Test<TestTraitsInit> obj2;
}
正如您所看到的,只有在某些情况下才有Init()
是有意义的是否可以检查类Traits
是否有Init()
函数,并仅在它存在时调用它
我知道一个非常简单的解决方案是使用空的Init()
函数,但我想要一个更好的解决方案:(
您可以基于表达式SFINAE:创建一些具有适当的SFINAE约束专门化的类模板maybe_call_init
template<typename T, typename = void>
struct maybe_call_init
{
static void maybe_call(Test<T>* obj) { }
};
template<typename T>
struct maybe_call_init<T,
decltype(T::Init(std::declval<Test<T>*>()), void(0))>
{
static void maybe_call(Test<T>* obj) { T::Init(obj); }
};
给定一个特性T
,如果T
定义了这样一个函数,maybe_call_init<T>::maybe_call(obj)
将调用T::Init(obj)
,否则它将不执行任何操作。
然后,您可以在原始类模板中这样使用它:
template<typename Traits>
class Test
{
public:
Test()
{
maybe_call_init<Traits>::maybe_call(this);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
}
private:
typename Traits::Type value;
friend Traits;
};
上述解决方案有点初级,可以通过将maybe_call_init
类模板及其专用化隐藏在detail
命名空间中,提供一个助手函数来完成实例化工作来进行改进。因此,考虑到这台机器:
namespace detail
{
template<typename T, typename U, typename = void>
struct maybe_call_init
{
static void maybe_call(U* obj) { }
};
template<typename T, typename U>
struct maybe_call_init<T, U,
decltype(T::Init(std::declval<U*>()), void(0))>
{
static void maybe_call(U* obj) { T::Init(obj); }
};
}
template<template<typename> class T, typename U>
void maybe_call_init(T<U>* obj)
{
detail::maybe_call_init<U, T<U>>::maybe_call(obj);
}
您最初的Test
类的构造函数现在可能如下所示:
template<typename Traits>
class Test
{
public:
Test()
{
maybe_call_init(this);
// ^^^^^^^^^^^^^^^^^^^^^
}
public:
typename Traits::Type value;
friend Traits;
};
这是一个的实际示例。
相关文章:
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- QTimer对象是否在单独的线程中运行?它的机制是什么
- 将派生的对象地址分配给基础指针和调用击路仪的机制
- 可以使类名和对象名相同服务于singleton的机制
- 在C++中创建"template"对象的机制