How to partial specialize a template member function in a template class?

Discussion in 'C++' started by PengYu.UT@gmail.com, Mar 13, 2007.

  1. Guest

    Hi,

    I want to partial specialize the member function doit. But it doesn't
    work. Could you please help me to figure out what is wrong?

    Thanks,
    Peng

    template <typename T>
    class A {
    public:
    A() {}
    template <typename T1>
    void doit();
    };

    template <>
    template <typename T>
    void A<T>::doit<double>() {
    std::cout << "double" << std::endl;
    }


    int main() {
    A<double> a;
    a.doit<double>();
    }
     
    , Mar 13, 2007
    #1
    1. Advertising

  2. wrote:
    > I want to partial specialize the member function doit. But it doesn't
    > work. Could you please help me to figure out what is wrong?


    Specialisations of class members are not allowed without first
    specialising the class itself.

    What problem are you trying to solve?

    >
    > Thanks,
    > Peng
    >
    > template <typename T>
    > class A {
    > public:
    > A() {}
    > template <typename T1>
    > void doit();
    > };
    >
    > template <>
    > template <typename T>
    > void A<T>::doit<double>() {
    > std::cout << "double" << std::endl;
    > }
    >
    >
    > int main() {
    > A<double> a;
    > a.doit<double>();
    > }


    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, Mar 13, 2007
    #2
    1. Advertising

  3. Piyo Guest

    Re: How to partial specialize a template member function in a templateclass?

    wrote:
    > Hi,
    >
    > I want to partial specialize the member function doit. But it doesn't
    > work. Could you please help me to figure out what is wrong?
    >
    > Thanks,
    > Peng
    >
    > template <typename T>
    > class A {
    > public:
    > A() {}
    > template <typename T1>
    > void doit();
    > };
    >
    > template <>
    > template <typename T>
    > void A<T>::doit<double>() {
    > std::cout << "double" << std::endl;
    > }
    >
    >
    > int main() {
    > A<double> a;
    > a.doit<double>();
    > }
    >


    It really depends on the requirements of your program.
    If your template member function has a distinct
    signature (your current example does not) then you can
    use simple function overloading to solve it for you
    as shown in the following example. Otherwise, you will
    need to specialize your primary template as Victor
    suggests.

    ------------------------------------------------------
    #include <iostream>

    using namespace std;

    template <typename T>
    class A {
    public:
    A() {}
    template <typename T1>
    void doit( T1 * p ) { cout << "Template" << endl; }

    void doit( void * p) { cout << "Specialized" << endl;}
    };

    int
    main()
    {
    A<int> foo;
    int *bar;
    void *baz;
    foo.doit( bar );
    foo.doit( baz );
    }
    -------------------------------------------
    This program prints:
    Template
    Specialized
     
    Piyo, Mar 13, 2007
    #3
  4. Guest

    On Mar 13, 5:23 pm, "Victor Bazarov" <> wrote:
    > wrote:
    > > I want to partial specialize the member function doit. But it doesn't
    > > work. Could you please help me to figure out what is wrong?

    >
    > Specialisations of class members are not allowed without first
    > specialising the class itself.
    >
    > What problem are you trying to solve?


    The problem that I encountered was that I tried to expand the
    interface of a member function of a template class. A bool argument
    was added to the member function.

    Later on, I found that it is better not to use a bool argument,
    because it results in runtime overhead. I want to supply it as an
    template argument, which is resolved at compile time. Then the runtime
    overhead of conditional branches can be avoid. However, it seems the
    problem is not that easy.

    I'm not sure how to specialize the class first. Could you please show
    it to me? BTW, I modify the examples to reflect my intent better. The
    first one is with branch. I want to modify it to eliminate the branch
    by template specialization. I want the solution with as less
    modification to the original code as possible. This requirement makes
    the refactoring process easier.

    /////////////code with branch
    #include <iostream>
    template <typename T>
    class A {
    public:
    A(T t) : _t(t) {}
    T doit(bool b) {
    if(b) return _t;
    else return - _t;
    }
    private:
    T _t;
    };

    int main() {
    A<double> a(10);

    std::cout << a.doit(true) << std::endl;
    }
    /////////////end code with branch

    ////////////code with template(not working)
    #include <iostream>
    template <typename T>
    class A {
    public:
    A(T t) : _t(t) {}
    template <bool B>
    T doit();// it was a function without any template
    // argument, which only return _t;
    private:
    T _t;
    };

    template <>
    template <typename T>
    T A<T>::doit<true>() {
    return _t;
    }

    template <>
    template <typename T>
    T A<T>::doit<false>() {
    return - _t;
    }

    int main() {
    A<double> a(10);

    std::cout << a.doit() << std::endl;
    }
     
    , Mar 14, 2007
    #4
  5. Piyo Guest

    Re: How to partial specialize a template member function in a templateclass?

    wrote:
    >
    > ////////////code with template(not working)
    > #include <iostream>
    > template <typename T>
    > class A {
    > public:
    > A(T t) : _t(t) {}
    > template <bool B>
    > T doit();// it was a function without any template
    > // argument, which only return _t;
    > private:
    > T _t;
    > };
    >
    > template <>
    > template <typename T>
    > T A<T>::doit<true>() {
    > return _t;
    > }
    >
    > template <>
    > template <typename T>
    > T A<T>::doit<false>() {
    > return - _t;
    > }
    >
    > int main() {
    > A<double> a(10);
    >
    > std::cout << a.doit() << std::endl;
    > }
    >


    Instead of using template member functions, have you
    considered just having two regular member functions
    that do what you want.
    ------------------------------------------------------
    template<typename T>
    class Test
    {
    public:

    T fooPlus() { return m_data; }
    T fooMinus() { return -m_data; }

    private:
    T m_data;
    };
    -----------------------------------------------------

    Can you show me a simple main() driver that actually
    uses what you want? In your current main:

    >> A<double> a(10);
    >>
    >> std::cout << a.doit() << std::endl;


    This does not work since
    a.doit() does not map to anything proper unless you do
    a.doit<true>() or a.doit<false>(). But if you are explicitly
    specifying true or false, it is not different from doing
    a.fooPlus() or a.fooMinus().

    Can you show me a situation where you need this special
    case you are talking about?
     
    Piyo, Mar 14, 2007
    #5
  6. Guest

    On Mar 13, 7:59 pm, Piyo <> wrote:
    > wrote:
    >
    > > ////////////code with template(not working)
    > > #include <iostream>
    > > template <typename T>
    > > class A {
    > > public:
    > > A(T t) : _t(t) {}
    > > template <bool B>
    > > T doit();// it was a function without any template
    > > // argument, which only return _t;
    > > private:
    > > T _t;
    > > };

    >
    > > template <>
    > > template <typename T>
    > > T A<T>::doit<true>() {
    > > return _t;
    > > }

    >
    > > template <>
    > > template <typename T>
    > > T A<T>::doit<false>() {
    > > return - _t;
    > > }

    >
    > > int main() {
    > > A<double> a(10);

    >
    > > std::cout << a.doit() << std::endl;
    > > }

    >
    > Instead of using template member functions, have you
    > considered just having two regular member functions
    > that do what you want.
    > ------------------------------------------------------
    > template<typename T>
    > class Test
    > {
    > public:
    >
    > T fooPlus() { return m_data; }
    > T fooMinus() { return -m_data; }
    >
    > private:
    > T m_data;};
    >
    > -----------------------------------------------------
    >
    > Can you show me a simple main() driver that actually
    > uses what you want? In your current main:
    >
    > >> A<double> a(10);

    >
    > >> std::cout << a.doit() << std::endl;

    >
    > This does not work since
    > a.doit() does not map to anything proper unless you do
    > a.doit<true>() or a.doit<false>(). But if you are explicitly
    > specifying true or false, it is not different from doing
    > a.fooPlus() or a.fooMinus().
    >
    > Can you show me a situation where you need this special
    > case you are talking about?


    The real situation comes when some other template function (f1) call
    the doit member function with a template argument.
    If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    function.
    With a.doit<true>() and a.doit<false>(), I can. See below.

    template <bool B>
    void f1(A<double> &a, many argument...) {
    many code here...
    a.doit<B>();
    many code here...

    }
     
    , Mar 14, 2007
    #6
  7. wrote:
    > [..]
    > The real situation comes when some other template function (f1) call
    > the doit member function with a template argument.
    > If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    > function.
    > With a.doit<true>() and a.doit<false>(), I can. See below.
    >
    > template <bool B>
    > void f1(A<double> &a, many argument...) {
    > many code here...
    > a.doit<B>();


    What's stopping you from writing

    if (B)
    a.doitTrue();
    else
    a.doitFalse();

    ?

    > many code here...
    >
    > }


    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, Mar 14, 2007
    #7
  8. Piyo Guest

    Re: How to partial specialize a template member function in a templateclass?

    wrote:
    > The real situation comes when some other template function (f1) call
    > the doit member function with a template argument.
    > If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    > function.
    > With a.doit<true>() and a.doit<false>(), I can. See below.
    >
    > template <bool B>
    > void f1(A<double> &a, many argument...) {
    > many code here...
    > a.doit<B>();
    > many code here...
    >
    > }
    >


    I am not convinced that it is such a great idea to do this since
    there is a lot of hoops and scaffolding to create just to do what
    you are thinking. There might be a better solution directly to your
    problem but I cannot think of it right now. Here is an example of
    specializing a friend class instead to serve as your accessor.

    -----------------------------------------------------------------
    template<typename T> class Test;

    template<bool enable, typename Type>
    struct getData;

    template<typename Type>
    struct getData<true,Type>
    {
    Type operator()( Test<Type> &b )
    {
    return b.m_data;
    }
    };

    template<typename Type>
    struct getData<false, Type>
    {
    Type operator()( Test<Type> &b )
    {
    return -b.m_data;
    }
    };


    template<typename T>
    class Test
    {
    public:

    template<bool enable, typename Type > friend struct getData;

    private:
    T m_data;
    };

    template <bool B>
    double f1( Test<double>& a )
    {
    getData<B, double> accessor;
    return accessor( a );
    }

    int
    main()
    {
    Test<double> foo;
    f1<true>( foo );
    f1<false>( foo );
    }
     
    Piyo, Mar 14, 2007
    #8
  9. Guest

    On Mar 14, 1:11 pm, Piyo <> wrote:
    > wrote:
    > > The real situation comes when some other template function (f1) call
    > > the doit member function with a template argument.
    > > If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    > > function.
    > > With a.doit<true>() and a.doit<false>(), I can. See below.

    >
    > > template <bool B>
    > > void f1(A<double> &a, many argument...) {
    > > many code here...
    > > a.doit<B>();
    > > many code here...

    >
    > > }

    >
    > I am not convinced that it is such a great idea to do this since
    > there is a lot of hoops and scaffolding to create just to do what
    > you are thinking. There might be a better solution directly to your
    > problem but I cannot think of it right now. Here is an example of
    > specializing a friend class instead to serve as your accessor.
    >
    > -----------------------------------------------------------------
    > template<typename T> class Test;
    >
    > template<bool enable, typename Type>
    > struct getData;
    >
    > template<typename Type>
    > struct getData<true,Type>
    > {
    > Type operator()( Test<Type> &b )
    > {
    > return b.m_data;
    > }
    >
    > };
    >
    > template<typename Type>
    > struct getData<false, Type>
    > {
    > Type operator()( Test<Type> &b )
    > {
    > return -b.m_data;
    > }
    >
    > };
    >
    > template<typename T>
    > class Test
    > {
    > public:
    >
    > template<bool enable, typename Type > friend struct getData;
    >
    > private:
    > T m_data;
    >
    > };
    >
    > template <bool B>
    > double f1( Test<double>& a )
    > {
    > getData<B, double> accessor;
    > return accessor( a );
    >
    > }
    >
    > int
    > main()
    > {
    > Test<double> foo;
    > f1<true>( foo );
    > f1<false>( foo );
    >
    > }


    This is essentially how I solved the problem. However, the problem
    still comes from software refactoring.

    Suppose, original, my class "A" does not have any template argument as
    shown in the following example. Later on I find out I need to change
    int to a template argument T. I can turn "A" into a templated class as
    if "A" does not have any template member function. I have to rely on
    the tricks in your example, which makes the refactoring process more
    expensive. I'm wondering if there is anything that can be changed in
    the C++ language to make this process easier.

    #include <iostream>

    class A {
    public:
    A(int t) : _t(t) {}
    template <bool B>
    int doit();
    private:
    int _t;
    };

    template <>
    int A::doit<true>() {
    return _t;

    }

    template <>
    int A::doit<false>() {
    return - _t;
    }

    int main ()
    {
    A a(10);
    std::cout << a.doit<true>() << std::endl;
    std::cout << a.doit<false>() << std::endl;
    }
     
    , Mar 14, 2007
    #9
  10. Guest

    On Mar 13, 10:29 pm, "Victor Bazarov" <> wrote:
    > wrote:
    > > [..]
    > > The real situation comes when some other template function (f1) call
    > > the doit member function with a template argument.
    > > If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    > > function.
    > > With a.doit<true>() and a.doit<false>(), I can. See below.

    >
    > > template <bool B>
    > > void f1(A<double> &a, many argument...) {
    > > many code here...
    > > a.doit<B>();

    >
    > What's stopping you from writing
    >
    > if (B)
    > a.doitTrue();
    > else
    > a.doitFalse();
    >
    > ?
    >
    > > many code here...

    >
    > > }


    In principle, it is OK. But this would result in less readable code.
    BTW, may I ask if the branch is resolved at compile time or runtime?

    Also, when expression template comes in, we might have to do something
    like
    if (B)
    many_thing_before_in_the_expression_template ....
    a.doitTrue()//note there is no ";"
    ....many_thing_after_in_the_expression_template;
    else
    many_thing_before_in_the_expression_template ....
    a.doitFalse()//note there is no ";"
    ....many_thing_after_in_the_expression_template;


    It is better if I write like the following:

    many_thing_before_in_the_expression_template ....
    a.doit<B>()//note there is no ";"
    ....many_thing_after_in_the_expression_template;
     
    , Mar 14, 2007
    #10
  11. wrote:
    > On Mar 13, 10:29 pm, "Victor Bazarov" <> wrote:
    >> wrote:
    >>> [..]
    >>> The real situation comes when some other template function (f1) call
    >>> the doit member function with a template argument.
    >>> If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    >>> function.
    >>> With a.doit<true>() and a.doit<false>(), I can. See below.

    >>
    >>> template <bool B>
    >>> void f1(A<double> &a, many argument...) {
    >>> many code here...
    >>> a.doit<B>();

    >>
    >> What's stopping you from writing
    >>
    >> if (B)
    >> a.doitTrue();
    >> else
    >> a.doitFalse();
    >>
    >> ?
    >>
    >>> many code here...

    >>
    >>> }

    >
    > In principle, it is OK. But this would result in less readable code.


    Really?

    > BTW, may I ask if the branch is resolved at compile time or runtime?


    That's unspecified. Most compilers will remove unnecessary code.

    >
    > Also, when expression template comes in, we might have to do something
    > like
    > if (B)
    > many_thing_before_in_the_expression_template ....
    > a.doitTrue()//note there is no ";"
    > ....many_thing_after_in_the_expression_template;
    > else
    > many_thing_before_in_the_expression_template ....
    > a.doitFalse()//note there is no ";"
    > ....many_thing_after_in_the_expression_template;
    >
    >
    > It is better if I write like the following:
    >
    > many_thing_before_in_the_expression_template ....
    > a.doit<B>()//note there is no ";"
    > ....many_thing_after_in_the_expression_template;


    Uh... This is all fine and dandy, but why can't you do

    many_thing_before_in_the_expression_template ....
    ( B ? a.doitIfBTrue() // note there is no ";"
    : a.doitIfBIsFalse() ) // note there is no ";"
    ....many_thing_after_in_the_expression_template;

    ?

    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, Mar 14, 2007
    #11
  12. Guest

    On Mar 14, 4:28 pm, "Victor Bazarov" <> wrote:
    > wrote:
    > > On Mar 13, 10:29 pm, "Victor Bazarov" <> wrote:
    > >> wrote:
    > >>> [..]
    > >>> The real situation comes when some other template function (f1) call
    > >>> the doit member function with a template argument.
    > >>> If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    > >>> function.
    > >>> With a.doit<true>() and a.doit<false>(), I can. See below.

    >
    > >>> template <bool B>
    > >>> void f1(A<double> &a, many argument...) {
    > >>> many code here...
    > >>> a.doit<B>();

    >
    > >> What's stopping you from writing

    >
    > >> if (B)
    > >> a.doitTrue();
    > >> else
    > >> a.doitFalse();

    >
    > >> ?

    >
    > >>> many code here...

    >
    > >>> }

    >
    > > In principle, it is OK. But this would result in less readable code.

    >
    > Really?
    >
    > > BTW, may I ask if the branch is resolved at compile time or runtime?

    >
    > That's unspecified. Most compilers will remove unnecessary code.
    >
    >
    >
    >
    >
    > > Also, when expression template comes in, we might have to do something
    > > like
    > > if (B)
    > > many_thing_before_in_the_expression_template ....
    > > a.doitTrue()//note there is no ";"
    > > ....many_thing_after_in_the_expression_template;
    > > else
    > > many_thing_before_in_the_expression_template ....
    > > a.doitFalse()//note there is no ";"
    > > ....many_thing_after_in_the_expression_template;

    >
    > > It is better if I write like the following:

    >
    > > many_thing_before_in_the_expression_template ....
    > > a.doit<B>()//note there is no ";"
    > > ....many_thing_after_in_the_expression_template;

    >
    > Uh... This is all fine and dandy, but why can't you do
    >
    > many_thing_before_in_the_expression_template ....
    > ( B ? a.doitIfBTrue() // note there is no ";"
    > : a.doitIfBIsFalse() ) // note there is no ";"
    > ....many_thing_after_in_the_expression_template;


    Yes, you can.

    In my expression, I have one instance of the following expression. But
    what if you have many instances, it will make the expression less
    readable. After all, a.doit<B>() is much more readable than if
    statement and ?: operator. And it requires less changes from the user
    side than using if statement and ?: operator.
    Better readability makes the program easier to maintain. Less changes
    make the program easier to be refactored.

    ( B ? a.doitIfBTrue() // note there is no ";"
    : a.doitIfBIsFalse() ) // note there is no ";"
     
    , Mar 15, 2007
    #12
  13. Guest

    On Mar 13, 10:29 pm, "Victor Bazarov" <> wrote:
    > wrote:
    > > [..]
    > > The real situation comes when some other template function (f1) call
    > > the doit member function with a template argument.
    > > If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    > > function.
    > > With a.doit<true>() and a.doit<false>(), I can. See below.

    >
    > > template <bool B>
    > > void f1(A<double> &a, many argument...) {
    > > many code here...
    > > a.doit<B>();

    >
    > What's stopping you from writing
    >
    > if (B)
    > a.doitTrue();
    > else
    > a.doitFalse();
    >
    > ?
    >
    > > many code here...

    >
    > > }


    Just to make sure. There is no runtime overhead in this code, right?
    Is the branch resolved at compile time?

    Thanks,
    Peng
     
    , Mar 15, 2007
    #13
  14. wrote:
    > On Mar 13, 10:29 pm, "Victor Bazarov" <> wrote:
    >> wrote:
    >>> [..]
    >>> The real situation comes when some other template function (f1) call
    >>> the doit member function with a template argument.
    >>> If I have a.fooPlus() or a.fooMinus(), I can not really template f1
    >>> function.
    >>> With a.doit<true>() and a.doit<false>(), I can. See below.

    >>
    >>> template <bool B>
    >>> void f1(A<double> &a, many argument...) {
    >>> many code here...
    >>> a.doit<B>();

    >>
    >> What's stopping you from writing
    >>
    >> if (B)
    >> a.doitTrue();
    >> else
    >> a.doitFalse();
    >>
    >> ?
    >>
    >>> many code here...

    >>
    >>> }

    >
    > Just to make sure. There is no runtime overhead in this code, right?
    > Is the branch resolved at compile time?


    Just to make sure. This is unspecified in the language Standard.

    But I have a question: WHAT runtime overhead? From where? You ask
    as if you know that it might be there, meaning, you have seen the
    overhead in a similar situation. Care to elaborate?

    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, Mar 15, 2007
    #14
  15. wrote:
    > On Mar 14, 4:28 pm, "Victor Bazarov" <> wrote:
    >> wrote:
    >>> On Mar 13, 10:29 pm, "Victor Bazarov" <>
    >>> wrote:
    >>>> wrote:
    >>>>> [..]
    >>>>> The real situation comes when some other template function (f1)
    >>>>> call the doit member function with a template argument.
    >>>>> If I have a.fooPlus() or a.fooMinus(), I can not really template
    >>>>> f1 function.
    >>>>> With a.doit<true>() and a.doit<false>(), I can. See below.

    >>
    >>>>> template <bool B>
    >>>>> void f1(A<double> &a, many argument...) {
    >>>>> many code here...
    >>>>> a.doit<B>();

    >>
    >>>> What's stopping you from writing

    >>
    >>>> if (B)
    >>>> a.doitTrue();
    >>>> else
    >>>> a.doitFalse();

    >>
    >>>> ?

    >>
    >>>>> many code here...

    >>
    >>>>> }

    >>
    >>> In principle, it is OK. But this would result in less readable code.

    >>
    >> Really?
    >>
    >>> BTW, may I ask if the branch is resolved at compile time or runtime?

    >>
    >> That's unspecified. Most compilers will remove unnecessary code.
    >>
    >>
    >>
    >>
    >>
    >>> Also, when expression template comes in, we might have to do
    >>> something like
    >>> if (B)
    >>> many_thing_before_in_the_expression_template ....
    >>> a.doitTrue()//note there is no ";"
    >>> ....many_thing_after_in_the_expression_template;
    >>> else
    >>> many_thing_before_in_the_expression_template ....
    >>> a.doitFalse()//note there is no ";"
    >>> ....many_thing_after_in_the_expression_template;

    >>
    >>> It is better if I write like the following:

    >>
    >>> many_thing_before_in_the_expression_template ....
    >>> a.doit<B>()//note there is no ";"
    >>> ....many_thing_after_in_the_expression_template;

    >>
    >> Uh... This is all fine and dandy, but why can't you do
    >>
    >> many_thing_before_in_the_expression_template ....
    >> ( B ? a.doitIfBTrue() // note there is no ";"
    >> : a.doitIfBIsFalse() ) // note there is no ";"
    >> ....many_thing_after_in_the_expression_template;

    >
    > Yes, you can.
    >
    > In my expression, I have one instance of the following expression. But
    > what if you have many instances, it will make the expression less
    > readable. After all, a.doit<B>() is much more readable than if
    > statement and ?: operator. And it requires less changes from the user
    > side than using if statement and ?: operator.
    > Better readability makes the program easier to maintain. Less changes
    > make the program easier to be refactored.


    Oh, bullshit (pardon my French).
    If you have "many_thing_before_in_the_blah" and then
    "many_thing_after_in_the_blah", what readability are you trying to
    claim here?

    >
    > ( B ? a.doitIfBTrue() // note there is no ";"
    > : a.doitIfBIsFalse() ) // note there is no ";"


    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, Mar 15, 2007
    #15
  16. Guest

    On Mar 14, 10:35 pm, "Victor Bazarov" <> wrote:
    > wrote:
    > > On Mar 14, 4:28 pm, "Victor Bazarov" <> wrote:
    > >> wrote:
    > >>> On Mar 13, 10:29 pm, "Victor Bazarov" <>
    > >>> wrote:
    > >>>> wrote:
    > >>>>> [..]
    > >>>>> The real situation comes when some other template function (f1)
    > >>>>> call the doit member function with a template argument.
    > >>>>> If I have a.fooPlus() or a.fooMinus(), I can not really template
    > >>>>> f1 function.
    > >>>>> With a.doit<true>() and a.doit<false>(), I can. See below.

    >
    > >>>>> template <bool B>
    > >>>>> void f1(A<double> &a, many argument...) {
    > >>>>> many code here...
    > >>>>> a.doit<B>();

    >
    > >>>> What's stopping you from writing

    >
    > >>>> if (B)
    > >>>> a.doitTrue();
    > >>>> else
    > >>>> a.doitFalse();

    >
    > >>>> ?

    >
    > >>>>> many code here...

    >
    > >>>>> }

    >
    > >>> In principle, it is OK. But this would result in less readable code.

    >
    > >> Really?

    >
    > >>> BTW, may I ask if the branch is resolved at compile time or runtime?

    >
    > >> That's unspecified. Most compilers will remove unnecessary code.

    >
    > >>> Also, when expression template comes in, we might have to do
    > >>> something like
    > >>> if (B)
    > >>> many_thing_before_in_the_expression_template ....
    > >>> a.doitTrue()//note there is no ";"
    > >>> ....many_thing_after_in_the_expression_template;
    > >>> else
    > >>> many_thing_before_in_the_expression_template ....
    > >>> a.doitFalse()//note there is no ";"
    > >>> ....many_thing_after_in_the_expression_template;

    >
    > >>> It is better if I write like the following:

    >
    > >>> many_thing_before_in_the_expression_template ....
    > >>> a.doit<B>()//note there is no ";"
    > >>> ....many_thing_after_in_the_expression_template;

    >
    > >> Uh... This is all fine and dandy, but why can't you do

    >
    > >> many_thing_before_in_the_expression_template ....
    > >> ( B ? a.doitIfBTrue() // note there is no ";"
    > >> : a.doitIfBIsFalse() ) // note there is no ";"
    > >> ....many_thing_after_in_the_expression_template;

    >
    > > Yes, you can.

    >
    > > In my expression, I have one instance of the following expression. But
    > > what if you have many instances, it will make the expression less
    > > readable. After all, a.doit<B>() is much more readable than if
    > > statement and ?: operator. And it requires less changes from the user
    > > side than using if statement and ?: operator.
    > > Better readability makes the program easier to maintain. Less changes
    > > make the program easier to be refactored.

    >
    > Oh, bullshit (pardon my French).


    Please be careful when you use these words in the groups.

    > If you have "many_thing_before_in_the_blah" and then
    > "many_thing_after_in_the_blah", what readability are you trying to
    > claim here?


    Maybe these things is not very readable in your opinion. But let's
    assume we can not do anything to change it. Or if needed, we can spend
    some effort to change them to make it more readable.

    > > ( B ? a.doitIfBTrue() // note there is no ";"
    > > : a.doitIfBIsFalse() ) // note there is no ";"


    But still the above things are less readable than a.doit<B>().

    Remember the problem comes from the fact that partial specialization
    of a template member function of a regular class is different from
    that of a templated class. I'm wondering why the C++ standard make
    this kind of distinction. Would this make code refactoring more
    painful.

    Thanks,
    Peng
     
    , Mar 15, 2007
    #16
  17. wrote:
    > On Mar 14, 10:35 pm, "Victor Bazarov" <> wrote:
    > [..]
    >>> ( B ? a.doitIfBTrue() // note there is no ";"
    >>> : a.doitIfBIsFalse() ) // note there is no ";"

    >
    > But still the above things are less readable than a.doit<B>().


    Well, wrap them in a function, and pass 'B' [and 'a' if need be] to it:

    a.doitWith(B)

    or

    doitWith(a, B)

    or whatever else. Don't be so hell-bent on using 'a.doit<B>()'. What
    is the point of the exercise? Is it to prove the impossibility? I am
    simply trying to show a way to do it, a work-around.

    Maintainability, readability, are both very subjective. Why insist on
    non-existent (albeit "more readable") way of doing things, when there
    is another, simple (and not REALLY less readable) way?

    > Remember the problem comes from the fact that partial specialization
    > of a template member function of a regular class is different from
    > that of a templated class. I'm wondering why the C++ standard make
    > this kind of distinction. Would this make code refactoring more
    > painful.


    I am not sure why one's not allowed to specialize a member template
    of a class template without first specializing the class template.
    You could ask about the rationale for it in comp.std.c++.

    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, Mar 15, 2007
    #17
    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. Peter Koch Larsen

    How to specialize member template function?

    Peter Koch Larsen, Jan 25, 2005, in forum: C++
    Replies:
    9
    Views:
    483
    Peter Koch Larsen
    Jan 25, 2005
  2. mrstephengross
    Replies:
    1
    Views:
    302
    Victor Bazarov
    Aug 2, 2005
  3. Replies:
    1
    Views:
    377
    Victor Bazarov
    Feb 17, 2006
  4. Imre
    Replies:
    2
    Views:
    344
    mlimber
    May 25, 2006
  5. toton
    Replies:
    3
    Views:
    402
    Victor Bazarov
    Jan 25, 2007
Loading...

Share This Page