шаблон шаблона с ++? - PullRequest
       13

шаблон шаблона с ++?

7 голосов
/ 04 июля 2011

Мне удалось создать некоторый класс свойств со всем, что мы ожидаем от одного. Я имею в виду, что при использовании вам не нужно вызывать функции, просто использование 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;
}

см. Свойство класса имеет 4 аргумента, а первым аргументом является сам тип класса. Я хотел бы знать, можем ли мы сделать что-нибудь для извлечения типа класса из двух потребностей свойства указателей на функции что-то вроде property <int, &setInt, &getInt> myInt;.

знаете ли вы какой-нибудь способ устранить первый параметр шаблона?

Ответы [ 4 ]

4 голосов
/ 04 июля 2011

Если вы хотите не указывать параметры типа в явном виде, следующий код будет соответствовать цели.Однако для этого кода требуется 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 имеет собственное свойство .Возможно, это будет проще, если это послужит цели.

3 голосов
/ 04 июля 2011

Успех наконец-то! 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.

Подано сообщение об ошибке (пожалуйста, проголосуйте):

Компилятор C ++ теряет членство функции указателя на член во время вывода шаблона, вызывает ICE


Microsoft обновила отчет об ошибках, чтобы сообщить, что они нашли исправление.

1 голос
/ 04 июля 2011

Если удаление параметров шаблона - это то, что вам нужно, то вы можете сделать это, но не удалив первый параметр шаблона. То, что вы можете сделать, это удалить параметры шаблона указателя на метод, потому что они действительно не нужны. Приведенный ниже код скомпилирован с 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;
}
1 голос
/ 04 июля 2011

Я хотел бы знать, можем ли мы что-нибудь сделать для извлечения типа класса из двух потребностей в свойствах указателей на функции.

Не совсем. Невозможно узнать тип класса указателя на член, даже с признаками типа метапрограммирования.

О, и это указатели на члены , а не указатели на функции. Они не одно и то же.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...