Use static type from template pointer type



  • Hi,

    Le title isn't really clear, but I didn't know how to write it, sorry if it's also a duplicate.

    I'm subclassing QAbstractListModel as a template class named AbstractListModel which contains an internal QList (of pointer types). Obviously, my subclass is a template to define the QList content, but I also use it with QVariants.

    I want the AbstractListModel subclasses to inherit from *AbstractListModel<MyClass > (which will set the QList content to <MyClass *> also) BUT I'm using the full type (not the pointer, the static type) to convert from QVariant, my problem is that I don't know how to write the full template type from the pointer one.

    Example:
    @template <typename T = int *>
    void test()
    {
    T a = 0; // Here, a is a pointer to int.
    ??????? // And here I want to declare an int
    }@

    Is there a way to declare a static type if you know that T is a pointer type?



  • Yes, there is a way in c++ 11, but I don't think it is very useful.
    @
    template <typename T = int *>
    void test()
    {
    T a = 0; // Here, a is a pointer to int.
    auto b = *a; // And here I want to declare an int
    std::cout << b << std::endl; // core dump is here :-)
    }
    @

    PS: Why not inverse it.
    @
    template <typename T = int>
    void test()
    {
    T a = 0;
    T* b = new T;
    std::cout << b << std::endl; // core dump is here :-)
    }
    @



  • This is just an example. The type will never be an int but a class, and there will be no default type.

    I wrote it that way only as a comprehensible example, so inversion is excluded (as the question is how to write the static type from the pointer type), as well as auto ;)

    Thanks anyway



  • Thank you for interesting question.
    BTW why auto is excluded ?

    I have another example. But it uses auto
    @
    /** http://www.cplusplus.com/reference/memory/pointer_traits/

    • g++ -std=c++11 -o test2 test2.cpp
      */
      // pointer_traits example
      #include <iostream>
      #include <memory>

    // using pointer_traits to determine return type:
    template <class T>
    typename std::pointer_traits<T>::element_type dereference_pointer (T pt) {
    return *pt;
    }

    class A
    {
    public:
    A() : m_number(0) {}
    ~A() {}

        void setNumber(int number) {
            m_number = number;
        }
        int number() const {
            return m_number;
        }
    
    private:
        int m_number;
    

    };

    class B
    {
    public:
    B() {}
    ~B() {}
    };

    int main(int, char**)
    {
    int* foo = new int(1);
    std::shared_ptr<int> bar (new int(2));

    std::cout << "foo: " << dereference_pointer (foo) << '\n';
    std::cout << "bar: " << dereference_pointer (bar) << '\n';
    
    delete foo;
    
    A* pa = new A;
    pa->setNumber(23);
    
    auto a = dereference_pointer(pa);
    a.setNumber(34);
    
    std::cout << "pa = " << pa->number() << std::endl;
    std::cout << "a = " << a.number() << std::endl;
    
    B* pb = new B;
    auto b = dereference_pointer(pb);
    b.setNumber(34);
    
    return 0;
    

    }
    @



  • [quote author="andreyc" date="1401232860"]BTW why auto is excluded ?
    [/quote]
    I wrongly thought auto was used to declare ints. So it's not excluded, my mistake.

    But as I'm reading your post, I think it's still now what I'm asking as I don't think using the value is useful, maybe my question isn't clear.

    Let's imagine I have this class:
    @template <typename T>
    class A
    {
    T m_dummy;
    }@

    Here, if I instantiate A with T = QWidget * (this is an example), m_dummy will be a pointer to QWidget.

    If I instantiate A with T = QWidget, m_dummy will be of type QWidget (the plain type, not a pointer).

    Now, my question is: How to write A to be able to instantiate it with T = QWidget * and to have m_dummy to be of type QWidget (the plain type, not the pointer, as is T) ?

    Hope it's clearer.



  • Are you sure that you need to declare a variable. Maybe you can use some getter function that will return type auto and compiler will deduce the type.
    Could you post an example that reflects your design.



  • [quote author="andreyc" date="1401243568"]Could you post an example that reflects your design.[/quote]

    What I previously wrote was part of what I need.

    @template <typename T>
    class A
    {
    private:
    QList<T> m_list;
    T m_tmp;
    }@

    Here, if I instantiate A with T = QWidget *, how to write m_tmp to be the plain type and not the pointer?

    I wonder how to do it, today I have a solution: Instantiate A with plain type and QList<T>*, but I didn't know how to write it if T = pointer.



  • [quote author="Max13" date="1401266922"]I wonder how to do it, today I have a solution: Instantiate A with plain type and QList<T>*, [/quote]
    That I was trying to say when I talking about "inverse it" :-)
    [quote author="Max13" date="1401266922"]but I didn't know how to write it if T = pointer.[/quote]I don't know it either. That is why I asked about getter function. With a function you can pass a pointer to a variable and a compiler can deduce the type using
    @
    template <class T>
    typename std::pointer_traits<T>::element_type dereference_pointer (T pt) {
    return *pt;
    }
    @

    Anyway, I'm glad that you've resolved the issue.

    Could you please prepend "[SOLVED]" to the title of your post. So the other good people will be able to find your solution.



  • [quote author="andreyc" date="1401268410"]Could you please prepend "[SOLVED]" to the title of your post.[/quote]

    Actually it's not solved ^^'
    My own problem is solved, but not "How to write it" :/



  • g++ 4.7.2 compiles it with -std=c++98, got no real idea whether it is in accordance with any standard:
    @#include <iostream>

    template<class T> struct Deref {
    typedef T Refed;
    };

    template<typename T> struct Deref<T *> {
    typedef T Refed;
    };

    template<typename T> void omg(T t) {
    typename Deref<T>::Refed defer(0);
    std::cout << defer << std::endl;
    }

    int main() {
    omg((int *)NULL);
    }@


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.