How to do explicit specialization of non-type template function

Discussion in 'C++' started by Bill, Feb 19, 2008.

  1. Bill

    Bill Guest

    Hi,
    I have a quetion how to specialization a non-type templat function, I
    use VC++ 2005.

    My code is:

    #include "stdafx.h"

    enum VariableType
    {
    enumASCII = 1,
    enumDOUBLE = 2,
    enumDURATION = 3,
    enumINTEGER = 4
    };

    template< VariableType >
    struct HrtTypes{
    };

    template< size_t _size >
    struct INTEGERS
    {
    typedef signed char value_type;
    typedef signed char* pointer;
    typedef HrtTypes<enumINTEGER> TypeTrait;
    enum { size = _size };
    };

    template<typename T>
    bool foo(T*, typename T::TypeTrait*);

    //specializaton for INTEGERS<1>,<2>, ...<n>
    template<typename T>
    bool foo(T*, HrtTypes<enumINTEGER>*)
    {
    return true;
    }

    int main()
    {
    INTEGERS<1>* p1;

    foo(p1, INTEGERS<1>::TypeTrait*(0));

    size_t n = 4;
    INTEGERS<4> p2;

    foo(p2, INTEGERS<4>::TypeTrait*(0));
    }

    I hope all INTEGERS<1>...type can use the specilization for template
    function foo(....). I think the compiler could get that
    HrtTypes<enumINTEGER> is same with INTEGERS<1>::TypeTrait, so foo(p1,
    INTEGERS<1>::TypeTrait*(0)) and foo(p2, INTEGERS<4>::TypeTrait*(0));
    can call the same function above.
    but it seems these not works.

    who can give me more comments
    Thanks very well.
    Bill, Feb 19, 2008
    #1
    1. Advertising

  2. Bill wrote:
    > I have a quetion how to specialization a non-type templat function, I
    > use VC++ 2005.
    >
    > My code is:
    >
    > #include "stdafx.h"


    That's not a standard header. You might be better off leaning the
    language without the use of precompiled headers, BTW.

    >
    > enum VariableType
    > {
    > enumASCII = 1,
    > enumDOUBLE = 2,
    > enumDURATION = 3,
    > enumINTEGER = 4
    > };
    >
    > template< VariableType >
    > struct HrtTypes{
    > };
    >
    > template< size_t _size >
    > struct INTEGERS
    > {
    > typedef signed char value_type;
    > typedef signed char* pointer;
    > typedef HrtTypes<enumINTEGER> TypeTrait;
    > enum { size = _size };
    > };
    >
    > template<typename T>
    > bool foo(T*, typename T::TypeTrait*);
    >
    > //specializaton for INTEGERS<1>,<2>, ...<n>
    > template<typename T>
    > bool foo(T*, HrtTypes<enumINTEGER>*)
    > {
    > return true;
    > }
    > [..]


    Sorry, you can't do that. You're trying to define a partial
    specialisation of a function template, which is not allowed.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Feb 19, 2008
    #2
    1. Advertising

  3. Bill

    Pete Becker Guest

    On 2008-02-19 11:10:13 -0500, "Victor Bazarov" <> said:

    > Bill wrote:
    >> I have a quetion how to specialization a non-type templat function, I
    >> use VC++ 2005.
    >>
    >> My code is:
    >>
    >> #include "stdafx.h"

    >
    > That's not a standard header. You might be better off leaning the
    > language without the use of precompiled headers, BTW.


    And, especially, without Microsoft's sledge hammer notion of
    precompiled headers.

    --
    Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    Standard C++ Library Extensions: a Tutorial and Reference
    (www.petebecker.com/tr1book)
    Pete Becker, Feb 19, 2008
    #3
  4. Victor Bazarov schrieb:
    > Sorry, you can't do that. You're trying to define a partial
    > specialisation of a function template, which is not allowed.


    Usually a work-around is to use function object and define a partial
    specialization of this class.


    Marcel
    Marcel Müller, Feb 19, 2008
    #4
  5. Bill

    Bill Guest

    Thanks for your answer,

    1. Yes, you are right, I agree with remove the stdafx.h from header
    file.
    2. I am still not clear why I can't use particial specialization here,
    doe's vc2005 not support it or the particial specialization not work
    in this case?
    Bill, Feb 20, 2008
    #5
  6. Bill

    Bill Guest

    On Feb 20, 1:01 am, Marcel Müller <>
    wrote:
    > Victor Bazarov schrieb:
    >
    > > Sorry, you can't do that.  You're trying to define a partial
    > > specialisation of a function template, which is not allowed.

    >
    > Usually a work-around is to use function object and define a partial
    > specialization of this class.
    >
    > Marcel


    Thank you, could you send more details?
    Bill, Feb 20, 2008
    #6
  7. Bill

    James Kanze Guest

    On Feb 20, 2:45 am, Bill <> wrote:

    [..]
    > 2. I am still not clear why I can't use particial specialization here,
    > doe's vc2005 not support it or the particial specialization not work
    > in this case?


    Because, as Victor said, there is no partial specialization of
    function templates. It doesn't exist in the language. You can
    overload function templates, or use partial specialization of a
    class template.

    In your particular case, in fact, it looks to me like you have
    overloaded the function template, and not used partial
    specialization. And after correcting the obvious typos in your
    code (no parentheses around the type specification in the C
    style cast, and a forgotten address-of operator in the second
    function call), it compiles with g++. (You really should use
    copy/paste when posting, to make sure that the code you post is
    the code actually causing the problems.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Feb 20, 2008
    #7
  8. Bill wrote:
    > On Feb 20, 1:01 am, Marcel Müller <>
    > wrote:
    >> Victor Bazarov schrieb:
    >>
    >>> Sorry, you can't do that. You're trying to define a partial
    >>> specialisation of a function template, which is not allowed.

    >> Usually a work-around is to use function object and define a partial
    >> specialization of this class.
    >>
    >> Marcel

    >
    > Thank you, could you send more details?


    Example:


    /*****************************************************************************
    *
    * cast traits class
    *
    *****************************************************************************/

    template <typename D, typename S>
    struct my_cast_traits
    { static D do_static_cast(S s)
    { return static_cast<D>(s);
    }
    static D do_dynamic_cast(S s)
    { return dynamic_cast<D>(s);
    }
    static D do_const_cast(S s)
    { return const_cast<D>(s);
    }
    // we will never overload the reinterpret_cast!
    };


    /*****************************************************************************
    *
    * template functions for convenience
    *
    *****************************************************************************/

    // wee need wrappers here
    template <typename D, typename S>
    inline D my_static_cast(S s)
    { return my_cast_traits<D,S>::do_static_cast(s);
    }
    template <typename D, typename S>
    inline D my_dynamic_cast(S s)
    { return my_cast_traits<D,S>::do_dynamic_cast(s);
    }
    template <typename D, typename S>
    inline D my_const_cast(S s)
    { return my_cast_traits<D,S>::do_const_cast(s);
    }


    /*****************************************************************************
    *
    * Example for specialization for casting boost::shared_ptr
    *
    *****************************************************************************/

    template <typename D, typename S>
    struct my_cast_traits<boost::shared_ptr<D>, boost::shared_ptr<S> >
    { static boost::shared_ptr<D> do_static_cast(boost::shared_ptr<S> s)
    { return boost::static_pointer_cast<D>(s);
    }
    static boost::shared_ptr<D> do_dynamic_cast(boost::shared_ptr<S> s)
    { return boost::dynamic_pointer_cast<D>(s);
    }
    static boost::shared_ptr<D> do_const_cast(boost::shared_ptr<S> s)
    { return boost::const_pointer_cast<D>(s);
    }
    };



    Now my_static_cast behaves exactly as static cast (see note below),
    except that you can additionally write

    boost::shared_ptr<X> x;
    boost::shared_ptr<Y> y = my_static_cast<boost::shared_ptr<Y>>(x);

    This static cast is normally not allowed. And this is an important
    difference to C style pointers.

    Practically I partially specialized the template function
    my_static_cast. Syntactically only a helper class is partially specialized.


    Note: since C++ knows nothing about side effect free functions they
    cannot be evaluated at compile time even if their arguments are compile
    time constants. This results in the difference that the above cast
    replacement removes the compile time constant attribute from any
    argument passed to it. The built-in static_cast function does not do this.
    In my opinion this is a principal lack in the C++ language.


    Marcel
    Marcel Müller, Feb 22, 2008
    #8
    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. J.T. Conklin
    Replies:
    1
    Views:
    439
    David Hilsee
    Aug 11, 2004
  2. Andy
    Replies:
    5
    Views:
    503
    Shezan Baig
    Jan 30, 2005
  3. Ferdi Smit
    Replies:
    8
    Views:
    2,512
  4. Joseph Turian
    Replies:
    2
    Views:
    464
  5. Replies:
    5
    Views:
    646
Loading...

Share This Page