创建“模板”的机制C ++中的对象 [英] Mechanism to create "template" objects in C++

查看:102
本文介绍了创建“模板”的机制C ++中的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要能够用一些默认值初始化对象,但是要从外部代码(不嵌入类本身)。对象暴露给外部编辑器,我不想一次又一次设置相同的值,只更改一些不同的值。因为我已经有模板类,我想从traits类做这个。

I want to be able to initialize objects with some default values, but to do this from external code(not embedded in the class itself). The objects are exposed to external editor and I don't want to set the same values again and again and change only some values that are different. As I have already template classes I want to do this from the "traits" class.

这是一个简单的我想要达到的目标:

This is a simple samle of what I want to achieve:

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()函数并仅在存在时才调用它?

As you can see it makes sense to have Init() only in some cases. Is it possible to check if class Traits has Init() function and call it only when it exists?

我知道一个非常简单的解决方案是具有空的 Init()函数,我想要一个更好的解决方案:)

I know that a very simple solution would be to have empty Init() functions, but I want a better solution:)

推荐答案

你可以创建一些类模板 maybe_call_init

You could create some class template maybe_call_init with a proper SFINAE-constrained specialization based on expression SFINAE:

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 maybe_call_init< T> :: maybe_call(obj)将调用 T :: Init(obj) if T 定义了这样一个函数,它什么都不做。

Given a trait T, maybe_call_init<T>::maybe_call(obj) will call T::Init(obj) if T defines such a function, and it will do nothing otherwise.

然后,您可以通过这种方式在原始类模板中使用它:

Then, you could use it in your original class template this way:

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 命名空间中的专门化,提供了一个帮助函数来进行实例化工作。所以给定这个机制:

The above solution is a bit rudimental, and could be improved by hiding the maybe_call_init class template and its specialization in a detail namespace, providing a helper function to do the instantiation work. So given this machinery:

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);
}

您的原始测试 class现在看起来像这样:

The constructor of your original Test class may now look like this:

template<typename Traits>
class Test
{
    public:
        Test()
        {
            maybe_call_init(this);
        //  ^^^^^^^^^^^^^^^^^^^^^
        }

    public:
        typename Traits::Type value;

    friend Traits;
};

这里是 活动示例

这篇关于创建“模板”的机制C ++中的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆