重载的模板类

时间:2017-01-11 15:22:10

标签: c++ templates

我在c ++中使用类似属性的系统,其中一个组件位于一个访问器模板类中,它创建了静态函数,然后我可以将指针传递给我的属性类以获取集合操作。 / p>

这里是访问者的样子:

template <typename T, typename V, V (T::*getf)(), void (T::*setf)(V)>
struct Accessor
{
    static V Get(T* obj)
    {
        return (obj->*getf)();
    }

    static void Set(T* obj, V aValue)
    {
        return (obj->*setf)(aValue);
    }
};

我正在使用访问器的测试类。注意SetFoo如何获取int,其中SetBar采用const int&amp;。

class TargetClass
{
    int foo;
    int bar;

public:
    TargetClass(int f, int b)
        : foo(f)
        , bar(b)
    {
    }

    int GetFoo()
    {
        return foo;
    }

    void SetFoo(int f)
    {
        foo = f;
    }

    int GetBar()
    {
        return bar;
    }

    void SetBar(const int& b)
    {
        bar = b;
    }
};

最后,这里是用法:

int main()
{
    TargetClass* target = new TargetClass(5, 3);

    // Works great
    typedef Accessor<TargetClass, int, &TargetClass::GetFoo, &TargetClass::SetFoo> fooAcessor;
    fooAcessor::Set(target, 13);
    int foo = fooAcessor::Get(target);

    // Doesn't work, because TargetClass::SetBar takes a const int& as an argument, instead of an int
    typedef Accessor<TargetClass, int, &TargetClass::GetBar, &TargetClass::SetBar> barAcessor;

    delete target;
    return 0;
}

我已尝试&#34;重载&#34; Acessor结构,所以它的第四个参数是一个const V&amp;,但这似乎不起作用。我可以在这里尝试做什么?

2 个答案:

答案 0 :(得分:1)

您可以为set函数的参数添加另一个模板参数:

template <typename T, typename V, typename VP, V(T::*getf)(), void (T::*setf)(VP)>

然后用于两种情况:

typedef Accessor<TargetClass, int, int, 
    &TargetClass::GetFoo, &TargetClass::SetFoo> fooAcessor;

typedef Accessor<TargetClass, int, const int&, 
    &TargetClass::GetBar, &TargetClass::SetBar> barAcessor;

完整计划:

template <typename T, typename V, typename VP, V(T::*getf)(), void (T::*setf)(VP)>
struct Accessor
{
    static V Get(T* obj)
    {
        return (obj->*getf)();
    }

    static void Set(T* obj, V aValue)
    {
        return (obj->*setf)(aValue);
    }
};

class TargetClass
{
    int foo;
    int bar;

public:
    TargetClass(int f, int b)
        : foo(f)
        , bar(b)
    {
    }

    int GetFoo()
    {
        return foo;
    }

    void SetFoo(int f)
    {
        foo = f;
    }

    int GetBar()
    {
        return bar;
    }

    void SetBar(const int& b)
    {
        bar = b;
    }
};

int main()
{
    TargetClass* target = new TargetClass(5, 3);

    // now has extra int parameter
    typedef Accessor<TargetClass, int, int, &TargetClass::GetFoo, &TargetClass::SetFoo> fooAcessor;
    fooAcessor::Set(target, 13);
    int foo = fooAcessor::Get(target);

    // Works now, because TargetClass::SetBar's function parameter was specified explicitly as const int&
    typedef Accessor<TargetClass, int, const int&, &TargetClass::GetBar, &TargetClass::SetBar> barAcessor;
    barAcessor::Set(target, 13);
    int bar = barAcessor::Get(target);

    delete target;
    return 0;
}

答案 1 :(得分:1)

如果您可以访问c ++ 17,并且假设建议的标准在此期间没有变化,您可以自动推断出类型:

template <typename F>
struct get_types;

template <typename T, typename V, typename... VP>
struct get_types<V(T::*)(VP...)>
{
    using return_type = V;
    using class_type = T;
};

template <auto getf, auto setf>
struct Accessor {
    using V = typename get_types<decltype(getf)>::return_type;
    using T = typename get_types<decltype(getf)>::class_type;
    static V Get(T* obj)
    {
        return (obj->*getf)();
    }

    static void Set(T* obj, V aValue)
    {
        return (obj->*setf)(aValue);
    }
};

class TargetClass {
    int foo;
    int bar;
public:
    TargetClass(int f, int b)
        : foo(f)
        , bar(b) {}
    int GetFoo() { return foo; }
    void SetFoo(int f) { foo = f; }
    int GetBar() { return bar; }
    void SetBar(const int& b) { bar = b; }
};

int main()
{
    TargetClass* target = new TargetClass(5, 3);
    using fooAccessor = Accessor<&TargetClass::GetFoo, &TargetClass::SetFoo>;

    fooAccessor::Set(target, 13);
    int foo = fooAccessor::Get(target);

    using barAcessor = Accessor<&TargetClass::GetBar, &TargetClass::SetBar>;
    barAcessor::Set(target, 13);
    int bar = barAcessor::Get(target);

    delete target;
    return foo + bar;
}

在撰写compiles on gcc 7 (snapshot)以上的程序时。

相关问题