模板c ++的模板?

时间:2011-07-04 09:40:54

标签: c++ templates properties

我已经设法创建了一些preperty类,其中包含了我们期望的所有内容。我的意思是在使用它时你不需要只使用operator =来调用函数来完成所有的工作。但是只有一件事我想如果我们可以解决它会很好:

template <class T, class X,void (T::*setFunc)(const X&),const X& (T::*getFunc)()const> class property
{ 
    T* const owner;
    X data;
    friend T;
    property(T*const  pOwner) : owner (pOwner)
    {
    }
public:
    property& operator = (const X& input){(owner->*setFunc)(input);return *this;}
    operator const X&()const {return (owner->*getFunc)();}
};

struct c
{
protected:
    void setInt(const int& data);
    const int& getInt() const;
public:
    c();
    property<c, int ,&setInt,&getInt> myInt;
};

c::c() : myInt(this)
{
}

void c::setInt(const int& data)
{
    myInt.data = data;
}
const int& c::getInt() const
{
    return myInt.data;
}

请参阅class属性有4个参数,第一个参数是类类型本身。我想知道我们是否可以做任何事情从两个函数指针属性需要中提取类类型。像property <int, &setInt, &getInt> myInt;这样的东西。

你知道如何消除第一个模板参数吗?

4 个答案:

答案 0 :(得分:4)

如果您想省略明确指定类型参数, 以下代码将符合目的。 但是,此代码需要VC2010。

template <class> struct class_type;
template <class C, class T> struct class_type< T(C::*) > { typedef C type; };

template <class> struct param_type;
template <class C, class T> struct param_type< void(C::*)(const T&) > {
    typedef T type;
};

template <class S, S setFunc, class G, G getFunc> struct property {
    typedef typename class_type<S>::type T;
    typedef typename param_type<S>::type X;
    T* const owner;
    X data;
    ....
};

#define PROPERTY(set, get) property<decltype(&set), &set, decltype(&get), &get>

struct c {
    void setInt(const int& data);
    const int& getInt() const;
    PROPERTY(setInt, getInt) myInt;
};

顺便说一句,MSVC有自己的 property。 如果达到目的,这可能会更容易。

答案 1 :(得分:3)

终于成功了! http://ideone.com/XJ7of

这个略好的版本仅适用于Comeau(不确定Comeau或gcc是否正确,但gcc抱怨friend指定)。

#include <iostream>
#include <typeinfo>

template <class T, class X,void (T::type::*setFunc)(const typename X::type&),const typename X::type& (T::type::*getFunc)()const> class property_impl
{ 
    typename T::type* const owner;
    friend typename T::type;
    property_impl(typename T::type* const pOwner) : owner (pOwner)
    {
    }
public:
    property_impl& operator = (const typename X::type& input){(owner->*setFunc)(input); return *this;}
    operator const typename X::type&()const {return (owner->*getFunc)();}
};

template<typename T> struct identity { typedef T type; };

template<typename Arg, typename T>
identity<T> match_memfn_classtype( void (T::*fn)(Arg) );

template<typename Arg, typename T>
identity<Arg> match_memfn_argtype( void (T::*fn)(Arg) );

#define property(setter,getter) property_impl<decltype(match_memfn_classtype(setter)), decltype(match_memfn_argtype(setter)), setter, getter>

struct C
{
private:
    int hiddenData;
protected:
    void setInt(const int& data) { hiddenData = data; std::cout << "setter used\n"; }
    const int& getInt() const { std::cout << "getter used\n"; return hiddenData; }
public:
    C() : myInt(this), hiddenData(5) {}
    property(&C::setInt,&C::getInt) myInt;
};

int main(void)
{
    C c;
    std::cout << "c.myInt = " << c.myInt << '\n';
    c.myInt = -1;
    std::cout << "c.myInt = " << c.myInt << '\n';
    return 0;
}

VC ++ 2010会对所有变体产生影响,尽管它可以非常简单地使用match_memfn_classtype

提交错误报告(请upvote):

C++ compiler loses member-ness of pointer-to-member-function during template deduction, causes ICE


微软更新了错误报告,说他们已经找到了解决办法。

答案 2 :(得分:1)

  

我想知道我们是否可以做任何事情从两个函数指针属性需要中提取类类型。

不是真的。即使使用元编程类型特征,也无法知道成员指针的类类型是什么。

哦,那些是成员指针,而不是函数指针。他们不是一回事。

答案 3 :(得分:1)

如果您需要删除模板参数,则可以执行此操作,但不能删除第一个模板参数。您可以做的是删除方法指针模板参数,因为这些参数确实不需要。下面的代码用gcc编译没有问题,它是你需要的简化版本,但是你可以看到它可以做些什么:

template<class T, class X> class Foo {
public:
    typedef const X& (T::*GetterFunc)() const;
    typedef void (T::*SetterFunc)(const X&);
    Foo(T* instance, GetterFunc getter, SetterFunc setter):
        _owner(instance), _getter(getter), _setter(setter) { }

    T* _owner;
    GetterFunc _getter;
    SetterFunc _setter;

};

class FooBar {
};

class Bar {
public:
    Bar(FooBar& foobar):_foobar(foobar) { }
    const FooBar& get() const { return _foobar; }
    void set(const FooBar& foobar) { _foobar = foobar; }
    FooBar _foobar;
};


int main() {
    FooBar foobar;
    Bar bar(foobar);
    Foo<Bar, FooBar> foo(&bar, &Bar::get, &Bar::set);
    return 0;
}