Virtual functions in template class issue

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Chris

    Virtual functions in template class issue

    I am having a very strange problem involving virtual
    functions in template classes. First of all, here is an
    extremely simplified structure of the two classes I am
    having problems with.

    template<class Type> class base
    {
    public:
    base& operator/=(const base&);
    Type *image;
    // There is more stuff here, but it is not necessary
    for this problem
    }

    class derived : public base<complex<do uble> >
    {
    // There is stuff here, but it is not necessary for
    this problem
    }

    template<class Type> base& base<Type>::ope rator/=(const
    base& im)
    {
    for(int i=0; i<loopLength; i++)
    {
    if(im.image[i] != 0) {
    image[i] = image[i] / im.image[i]; }
    else {
    image[i] = 0; }
    }
    return *this;
    }

    Now as that stands everything works fine, as it should.
    The problem comes when I try to make the operator/
    function a virtual function in base. I want to derive
    another class from base that needs a different
    implementation of the operator, but derived can use the
    same implementation. So, the only change I made to the
    code is:

    template<class Type> class base
    {
    public:
    virtual base& operator/=(const base&);
    Type *image;
    // There is more stuff here, but it is not necessary
    for this problem
    }

    It seems to me that this should all still work, but
    instead I get 23 strange errors when I try to compile the
    code with the virtual function. I should point out that
    base and derived are in separate files and these errors
    appear when the source for derived compiles. I don't
    understand why I get these errors at all. They all come
    from the line of code that contains the if(im.image[i] !=
    0). I actually have other operators that get the same
    errors. They all come from comparisons in if statements
    such as if(im.image[i] != image[i]) and they are all
    nearly identical except for the operator they list.

    I am completely baffled so please help me. Why does it
    work completely fine without the virtual?

    Chris



    The 23 Errors
    -----------------------------------------

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    _Ty &,const std::complex<_T y> &)' : could not deduce
    template argument for 'const std::complex<_T y> &'
    from 'int'

    Image.cpp(500): error C2782: 'bool std::operator !=(const
    std::complex<_T y> &,const _Ty &)' : template
    parameter '_Ty' is ambiguous

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::complex<_T y> &,const std::complex<_T y> &)' : could
    not deduce template argument for 'const std::complex<_T y>
    &' from 'int'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &,const _Elem
    *)' : could not deduce template argument for 'const
    std::basic_stri ng<_Elem,_Trait s,_Ax> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &,const _Elem
    *)' : could not deduce template argument for 'const
    std::basic_stri ng<_Elem,_Trait s,_Ax> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &,const _Elem
    *)' : could not deduce template argument for 'const
    std::basic_stri ng<_Elem,_Trait s,_Ax> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    _Elem *,const std::basic_stri ng<_Elem,_Trait s,_Alloc>
    &)' : could not deduce template argument for 'const T1 *'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &,const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &)' : could not
    deduce template argument for 'const
    std::basic_stri ng<_Elem,_Trait s,_Ax> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &,const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &)' : could not
    deduce template argument for 'const
    std::basic_stri ng<_Elem,_Trait s,_Ax> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &,const
    std::basic_stri ng<_Elem,_Trait s,_Alloc> &)' : could not
    deduce template argument for 'const
    std::basic_stri ng<_Elem,_Trait s,_Ax> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::allocator< _Ty> &,const std::allocator< _Other> &)' :
    could not deduce template argument for 'const
    std::allocator< _Ty> &' from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::allocator< _Ty> &,const std::allocator< _Other> &)' :
    could not deduce template argument for 'const
    std::allocator< _Ty> &' from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::allocator< _Ty> &,const std::allocator< _Other> &)' :
    could not deduce template argument for 'const
    std::allocator< _Ty> &' from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::istreambuf _iterator<_Elem ,_Traits> &,const
    std::istreambuf _iterator<_Elem ,_Traits> &)' : could not
    deduce template argument for 'const
    std::istreambuf _iterator<_Elem ,_Traits> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::istreambuf _iterator<_Elem ,_Traits> &,const
    std::istreambuf _iterator<_Elem ,_Traits> &)' : could not
    deduce template argument for 'const
    std::istreambuf _iterator<_Elem ,_Traits> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::istreambuf _iterator<_Elem ,_Traits> &,const
    std::istreambuf _iterator<_Elem ,_Traits> &)' : could not
    deduce template argument for 'const
    std::istreambuf _iterator<_Elem ,_Traits> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::reverse_it erator<_RanIt> &,const
    std::reverse_it erator<_RanIt> &)' : could not deduce
    template argument for 'const
    std::reverse_it erator<_RanIt> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::reverse_it erator<_RanIt> &,const
    std::reverse_it erator<_RanIt> &)' : could not deduce
    template argument for 'const
    std::reverse_it erator<_RanIt> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::reverse_it erator<_RanIt> &,const
    std::reverse_it erator<_RanIt> &)' : could not deduce
    template argument for 'const
    std::reverse_it erator<_RanIt> &'
    from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::pair<_Ty1, _Ty2> &,const std::pair<_Ty1, _Ty2> &)' :
    could not deduce template argument for 'const
    std::pair<_Ty1, _Ty2> &' from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::pair<_Ty1, _Ty2> &,const std::pair<_Ty1, _Ty2> &)' :
    could not deduce template argument for 'const
    std::pair<_Ty1, _Ty2> &' from 'std::complex<d ouble>'

    Image.cpp(500): error C2784: 'bool std::operator !=(const
    std::pair<_Ty1, _Ty2> &,const std::pair<_Ty1, _Ty2> &)' :
    could not deduce template argument for 'const
    std::pair<_Ty1, _Ty2> &' from 'std::complex<d ouble>'

    Image.cpp(500): error C2676: binary '!
    =' : 'std::complex<d ouble>' does not define this operator
    or a conversion to a type acceptable to the predefined
    operator

  • Bo Persson

    #2
    Re: Virtual functions in template class issue


    "Chris" <chawkins@ufl.e du> skrev i meddelandet
    news:049801c367 6e$f383f200$a50 1280a@phx.gbl.. .[color=blue]
    > I am having a very strange problem involving virtual
    > functions in template classes. First of all, here is an
    > extremely simplified structure of the two classes I am
    > having problems with.
    >
    > template<class Type> class base
    > {
    > public:
    > base& operator/=(const base&);
    > Type *image;
    > // There is more stuff here, but it is not necessary
    > for this problem
    > }[/color]

    I guess that in the real code, all the classes are terminated by a
    semicolon. :-)
    [color=blue]
    >
    > class derived : public base<complex<do uble> >
    > {
    > // There is stuff here, but it is not necessary for
    > this problem
    > }
    >
    > template<class Type> base& base<Type>::ope rator/=(const[/color]

    I think the return value should be

    base<Type>&
    [color=blue]
    > base& im)
    > {
    > for(int i=0; i<loopLength; i++)
    > {
    > if(im.image[i] != 0) {[/color]

    And here is your missing operator!=(), since the complex types cannot
    be compared to int. Change it to 0.0 and it will compile.
    [color=blue]
    > image[i] = image[i] / im.image[i]; }
    > else {
    > image[i] = 0; }
    > }
    > return *this;
    > }
    >[/color]



    Bo Persson
    bop2@telia.com

    Comment

    • Craig Powers

      #3
      [multipost] Re: Virtual functions in template class issue

      Also addressed in vc.language and vc.stl.

      Please don't multipost. If you must post the same message to multiple
      groups, you should crosspost.

      --
      Craig Powers
      MVP - Visual C++

      Comment

      • John Madsen

        #4
        Re: Virtual functions in template class issue

        "Chris" <chawkins@ufl.e du> wrote in message news:<049801c36 76e$f383f200$a5 01280a@phx.gbl> ...[color=blue]
        > I am having a very strange problem involving virtual
        > functions in template classes. First of all, here is an
        > extremely simplified structure of the two classes I am
        > having problems with.
        >
        > template<class Type> class base
        > {
        > public:
        > base& operator/=(const base&);
        > Type *image;
        > // There is more stuff here, but it is not necessary
        > for this problem
        > }
        >
        > class derived : public base<complex<do uble> >
        > {
        > // There is stuff here, but it is not necessary for
        > this problem
        > }
        >
        > template<class Type> base& base<Type>::ope rator/=(const
        > base& im)[/color]

        This needs to be:
        template<class Type> base<Type>& base<Type>::ope rator/=(const
        base<Type>& im)
        [color=blue]
        > {
        > for(int i=0; i<loopLength; i++)
        > {
        > if(im.image[i] != 0) {[/color]

        Your use of literal 0 here should be Type(0). As it stands, the
        compiler needs to do 2 conversions to turn 0 into a
        std::complex<do uble>. First, 0 (an int) needs to be converted to a
        double, then the double needs to be converted to a complex<double> .
        The compiler won't do 2 conversions, so you need to help it out with
        one.
        [color=blue]
        > image[i] = image[i] / im.image[i]; }
        > else {
        > image[i] = 0; }
        > }
        > return *this;
        > }
        >[/color]

        [snip]
        [color=blue]
        >
        > It seems to me that this should all still work, but
        > instead I get 23 strange errors when I try to compile the
        > code with the virtual function. I should point out that[/color]

        The 23 errors come from the fact that there are 23 operator!=()s in
        scope and it's trying all of them looking for a match.

        [snip]
        [color=blue]
        > I am completely baffled so please help me. Why does it
        > work completely fine without the virtual?
        >[/color]

        virtual is a red-herring here. If you eliminate the derived class and
        make operator/= non-virtual, the follow will still produce the 23
        errors:

        int main() {
        base<std::compl ex<double> > x;
        x /= x;
        }

        "x /= x" is needed to force the instantiation of base<T>::operat or/=,
        where the real problem is. Using virtual also forces that
        instantiation so that the compiler can generate the vtables for base
        and derived.

        Hope this helps,

        John

        Comment

        Working...