template specialization for pointer-to-type

Discussion in 'C++' started by .rhavin grobert, Jun 30, 2008.

  1. guess you have the following:

    _________________________________________________
    template <class T>
    class CQVector
    {
    public:
    // find an element, returns index or -1 if none is found
    int find(int id) const;
    private:
    std::vector<T> m_vec;
    };

    template <class T>
    int CQVector<T>::find(int id) const
    {
    int iCnt = m_vec.size();
    while (iCnt-->0)
    {
    if (m_vec[iCnt].ID() == id)
    break;
    }
    return iCnt;
    }
    _________________________________________________

    this finds an element in the vector by calling elements fn ID() and
    compiles for all structures/classes that have an ID() memeber-fn
    returning something comparable to int.


    now i also want the possibility to store pointers, eg

    CQVector<MyClass*> m_foo;

    and need some specialisation that does a...
    _________________________________________________

    int iCnt = m_vec.size();
    while (iCnt-->0)
    {
    if (m_vec[iCnt]->ID() == id)
    break;
    }
    return iCnt;
    _________________________________________________

    what syntax is need ed for the specialisation?
    something like template<class*T> doesnt work...

    TIA, -.rhavin;)
     
    .rhavin grobert, Jun 30, 2008
    #1
    1. Advertising

  2. .rhavin grobert

    Barry Guest

    On 7ÔÂ1ÈÕ, ÉÏÎç2ʱ59·Ö, ".rhavin grobert" <> wrote:
    > guess you have the following:
    >
    > _________________________________________________
    > template <class T>
    > class CQVector
    > {
    > public:
    > // find an element, returns index or -1 if none is found
    > int find(int id) const;
    > private:
    > std::vector<T> m_vec;
    >
    > };
    >
    > template <class T>
    > int CQVector<T>::find(int id) const
    > {
    > int iCnt = m_vec.size();
    > while (iCnt-->0)
    > {
    > if (m_vec[iCnt].ID() == id)
    > break;
    > }
    > return iCnt;}
    >
    > _________________________________________________
    >
    > this finds an element in the vector by calling elements fn ID() and
    > compiles for all structures/classes that have an ID() memeber-fn
    > returning something comparable to int.
    >
    > now i also want the possibility to store pointers, eg
    >
    > CQVector<MyClass*> m_foo;
    >
    > and need some specialisation that does a...
    > _________________________________________________
    >
    > int iCnt = m_vec.size();
    > while (iCnt-->0)
    > {
    > if (m_vec[iCnt]->ID() == id)
    > break;
    > }
    > return iCnt;
    > _________________________________________________
    >
    > what syntax is need ed for the specialisation?
    > something like template<class*T> doesnt work...
    >



    template <class T>
    class CQVector<T*>
    {
    ...
    };
     
    Barry, Jul 1, 2008
    #2
    1. Advertising

  3. .rhavin grobert

    Eric Pruneau Guest

    ".rhavin grobert" <> a écrit dans le message de news:
    ...
    > guess you have the following:
    >
    > _________________________________________________
    > template <class T>
    > class CQVector
    > {
    > public:
    > // find an element, returns index or -1 if none is found
    > int find(int id) const;
    > private:
    > std::vector<T> m_vec;
    > };
    >
    > template <class T>
    > int CQVector<T>::find(int id) const
    > {
    > int iCnt = m_vec.size();
    > while (iCnt-->0)
    > {
    > if (m_vec[iCnt].ID() == id)
    > break;
    > }
    > return iCnt;
    > }
    > _________________________________________________
    >
    > this finds an element in the vector by calling elements fn ID() and
    > compiles for all structures/classes that have an ID() memeber-fn
    > returning something comparable to int.
    >
    >
    > now i also want the possibility to store pointers, eg
    >
    > CQVector<MyClass*> m_foo;
    >
    > and need some specialisation that does a...
    > _________________________________________________
    >
    > int iCnt = m_vec.size();
    > while (iCnt-->0)
    > {
    > if (m_vec[iCnt]->ID() == id)
    > break;
    > }
    > return iCnt;
    > _________________________________________________
    >
    > what syntax is need ed for the specialisation?
    > something like template<class*T> doesnt work...
    >
    > TIA, -.rhavin;)



    No need to partially specialize your class by the way. Here an example.


    #include <boost/utility.hpp>
    #include <boost/type_traits.hpp>

    using namespace std;

    //This template function will be called only if T is a pointer. return type
    is int
    template<typename T>
    typename boost::enable_if_c<boost::is_pointer<T>::value, int>::type
    Do() {return 1;}

    //This template function will be called only if T is NOT a pointer. return
    type is int
    template<typename T>
    typename boost::disable_if_c<boost::is_pointer<T>::value, int>::type
    Do() {return 2;}

    template<typename T>
    class A
    {
    public:
    int DoSomething()
    {
    return Do<T>(); // Do actually take careof doing the right thing
    depending on T
    }
    };

    int main()
    {
    A<int> a1;
    A<int*> a2;
    cout <<a1.DoSomething() <<endl; // print 2
    cout <<a2.DoSomething() <<endl; // print 1
    return 0;
    }

    Ok I agree that the Do<T> function template could look a little (ok maybe
    not just a little...) strange at first sight but it is not actually that
    bad.

    take for example

    boost::enable_if_c<boost::is_pointer<T>::value, int>::type

    there is 2 template arg to enable_if_c
    1.boost::is_pointer<T>::value
    2. int
     
    Eric Pruneau, Jul 1, 2008
    #3
  4. .rhavin grobert

    Eric Pruneau Guest

    >
    > No need to partially specialize your class by the way. Here an example.
    >
    >
    > #include <boost/utility.hpp>
    > #include <boost/type_traits.hpp>
    >
    > using namespace std;
    >
    > //This template function will be called only if T is a pointer. return
    > type is int
    > template<typename T>
    > typename boost::enable_if_c<boost::is_pointer<T>::value, int>::type
    > Do() {return 1;}
    >
    > //This template function will be called only if T is NOT a pointer.
    > return type is int
    > template<typename T>
    > typename boost::disable_if_c<boost::is_pointer<T>::value, int>::type
    > Do() {return 2;}
    >
    > template<typename T>
    > class A
    > {
    > public:
    > int DoSomething()
    > {
    > return Do<T>(); // Do actually take careof doing the right thing
    > depending on T
    > }
    > };
    >
    > int main()
    > {
    > A<int> a1;
    > A<int*> a2;
    > cout <<a1.DoSomething() <<endl; // print 2
    > cout <<a2.DoSomething() <<endl; // print 1
    > return 0;
    > }
    >
    > Ok I agree that the Do<T> function template could look a little (ok maybe
    > not just a little...) strange at first sight but it is not actually that
    > bad.
    >
    > take for example
    >
    > boost::enable_if_c<boost::is_pointer<T>::value, int>::type
    >
    > there is 2 template arg to enable_if_c
    > 1.boost::is_pointer<T>::value
    > 2. int



    Sorry, I pushed the wrong button...

    ok so boost::is_pointer<T>::value will evaluate to true if T is a pointer
    and false otherwise.
    Inside enable_if_c, there is a simple typedef:
    typedef T type;
    it happen thet the second argument of the enable_if_c template is T (in our
    case int)
    so enable_if_c<true,int>::type == int and enable_if_c<true,MyClass>::type
    == MyClass, and so on

    So we can use the enable_if_c template as the return argument four our Do
    function template.

    Now what haapen when boost::is_pointer<T>::value evaluate to false? It is a
    substitution failure (see the SFINAE principle). In short the compiler will
    just reject the template and search for a better match (ok, if he does not
    find a better match he will give you an error). In our case, the second Do
    function will match for every non pointer type.

    In your case, you seem to have only 1 function to "specialize"and it it is a
    really simple function, so if you can install boost (www.boost.org) you
    should consider this option.

    ----------------------
    Eric Pruneau
     
    Eric Pruneau, Jul 1, 2008
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. David B. Held
    Replies:
    2
    Views:
    483
    Rob Williscroft
    Oct 26, 2003
  2. case2005
    Replies:
    3
    Views:
    1,859
    Nicolas Pavlidis
    Feb 13, 2005
  3. Joseph Turian
    Replies:
    2
    Views:
    492
  4. Oskar Enoksson
    Replies:
    8
    Views:
    638
    Oskar Enoksson
    Feb 22, 2007
  5. Replies:
    5
    Views:
    669
Loading...

Share This Page