overloading template operator arguments?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven T. Hatton

    #1

    overloading template operator arguments?

    The comperable operator*() to that shown here works for a non-template
    class:

    template <typename T>
    inline Vector3<T> operator*(const Vector3<T>& v, const T& n)
    {
    Vector3<T> t(v);
    return t *= n;
    }

    For example let Vector3f be a vector of float values. This works fine:
    inline Vector3f operator*(const Vector3f& v, const float& n)
    {
    Vector3f t(v);
    return t *= n;
    }

    It also works when I overload the template form of the operator*=(). For
    example this works for the same template class where the first function
    shown above fails:

    template <typename T>
    inline Vector3<T>& Vector3<T>::ope rator*=(const T& n)
    {
    _v[0] *= n;
    _v[1] *= n;
    _v[2] *= n;
    return *this;
    }

    If I replace the T& n with double& n in the first function, it works.

    The error I get when using the first form above is this:
    error: no match for 'operator*' in 'v3t0 * 5'

    Where I have defined:
    Vector3<T> v3t0;

    Why?
    --
    "If our hypothesis is about anything and not about some one or more
    particular things, then our deductions constitute mathematics. Thus
    mathematics may be defined as the subject in which we never know what we
    are talking about, nor whether what we are saying is true." - Bertrand
    Russell

  • John Harrison

    #2
    Re: overloading template operator arguments?


    "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message
    news:386dncZl1p ALjsDcRVn-tA@speakeasy.ne t...[color=blue]
    > The comperable operator*() to that shown here works for a non-template
    > class:
    >
    > template <typename T>
    > inline Vector3<T> operator*(const Vector3<T>& v, const T& n)
    > {
    > Vector3<T> t(v);
    > return t *= n;
    > }
    >
    > For example let Vector3f be a vector of float values. This works fine:
    > inline Vector3f operator*(const Vector3f& v, const float& n)
    > {
    > Vector3f t(v);
    > return t *= n;
    > }
    >
    > It also works when I overload the template form of the operator*=(). For
    > example this works for the same template class where the first function
    > shown above fails:
    >
    > template <typename T>
    > inline Vector3<T>& Vector3<T>::ope rator*=(const T& n)
    > {
    > _v[0] *= n;
    > _v[1] *= n;
    > _v[2] *= n;
    > return *this;
    > }
    >
    > If I replace the T& n with double& n in the first function, it works.
    >
    > The error I get when using the first form above is this:
    > error: no match for 'operator*' in 'v3t0 * 5'
    >
    > Where I have defined:
    > Vector3<T> v3t0;
    >
    > Why?[/color]

    I'm a bit confused with all these different operators and cases. Could you
    provide a complete non-working code sample?

    However one guess would be that you need

    v3t0 * 5.0

    assuming the v3t0 is of type Vector3<double> because C++ will not deduce the
    T is double from the first argument, only from the second, and since you
    provided an int, it then looking for Vector3<int> as the first argument.

    The rules about when C++ can make deductions about template parameters are
    quite complex and I'm not able to look them up right now so my explanation
    above might not be completely accurate even if the suggested correction is.

    john


    Comment

    • Steven T. Hatton

      #3
      Re: overloading template operator arguments?

      John Harrison wrote:
      [color=blue]
      > I'm a bit confused with all these different operators and cases. Could you
      > provide a complete non-working code sample?[/color]

      See below.
      [color=blue]
      > However one guess would be that you need
      >
      > v3t0 * 5.0[/color]

      Darn close! v3t0 * 5.0f
      [color=blue]
      > assuming the v3t0 is of type Vector3<double> because C++ will not deduce
      > the T is double from the first argument, only from the second, and since
      > you provided an int, it then looking for Vector3<int> as the first
      > argument.[/color]

      That can't be exactly what's happening because it fails with both prefix and
      postfix operator*(); I think the answer to my problem is to explicitly cast
      the scaler operands to T. I.e., v3t0 * T(5);
      [color=blue]
      > The rules about when C++ can make deductions about template parameters are
      > quite complex and I'm not able to look them up right now so my explanation
      > above might not be completely accurate even if the suggested correction
      > is.
      >
      > john[/color]
      The code show results in this:
      Fri Oct 01 13:20:19:> g++ -o vect main.cc
      main.cc: In function `int main()':
      main.cc:6: error: no match for 'operator*' in '5 * v0'

      If I simply swap the comments show below, the code will compile. Note that T
      is float in main();

      /*
      Vect.hh
      */
      #ifndef VECT_HH
      #define VECT_HH

      #include <vector>
      #include <iostream>

      namespace{
      using std::ostream;
      using std::vector;
      }

      template<typena me T>
      class Vect{
      public:
      Vect(const T& x,
      const T& y,
      const T& z)
      :_v(3)
      {
      _v[0]=x;
      _v[1]=y;
      _v[2]=z;
      }

      inline Vect<T>& operator*=(cons t T& n);
      std::ostream& print(ostream& out) const;

      private:
      vector<T> _v;
      };

      template<typena me T>
      Vect<T>& Vect<T>::operat or*=(const T& n)
      {
      _v[0] *= n;
      _v[1] *= n;
      _v[2] *= n;
      return *this;
      }

      template<typena me T>
      //Vect<T> operator*(const double& n, const Vect<T>& v)
      Vect<T> operator*(const T& n, const Vect<T>& v)
      {
      Vect<T> t(v);
      return t *= n;
      }

      template<typena me T>
      //Vect<T> operator*(const Vect<T>& v, const double& n)
      Vect<T> operator*(const Vect<T>& v, const T& n)
      {
      Vect<T> t(v);
      return t *= n;
      }

      template<typena me T>
      ostream& Vect<T>::print( ostream& out) const
      {
      return out
      << "Vect<T> = {"
      << _v[0] << ","
      << _v[1] << ","
      << _v[2] << "}\n";
      }

      template<typena me T>
      ostream& operator<<(ostr eam& out, const Vect<T>& v)
      {
      return v.print(out);
      }

      #endif



      /*
      main.cc
      */
      #include <iostream>
      #include "Vect.hh"

      int main() {
      Vect<float> v0(3,4,5);
      Vect<float> v1 = 5 * v0;
      std::cout
      << "v0 == " << v0
      << "v1 == " << v1;
      return 0;
      }

      --
      "If our hypothesis is about anything and not about some one or more
      particular things, then our deductions constitute mathematics. Thus
      mathematics may be defined as the subject in which we never know what we
      are talking about, nor whether what we are saying is true." - Bertrand
      Russell

      Comment

      • Victor Bazarov

        #4
        Re: overloading template operator arguments?

        Steven T. Hatton wrote:[color=blue]
        > [...]
        > template<typena me T>
        > //Vect<T> operator*(const double& n, const Vect<T>& v)
        > Vect<T> operator*(const T& n, const Vect<T>& v)
        > {
        > Vect<T> t(v);
        > return t *= n;
        > }[/color]

        Try

        template<class T, class U> Vect<U> operator *(T t, const Vect<U>& v)
        {
        Vect<U> vv(v);
        return vv *= t;
        }
        [color=blue]
        > [..][/color]

        V

        Comment

        • John Harrison

          #5
          Re: overloading template operator arguments?


          "Steven T. Hatton" <susudata@setid ava.kushan.aa> wrote in message
          news:88ydnRzFv5 bbN8DcRVn-qQ@speakeasy.ne t...[color=blue]
          > John Harrison wrote:
          >[color=green]
          >> I'm a bit confused with all these different operators and cases. Could
          >> you
          >> provide a complete non-working code sample?[/color]
          >
          > See below.
          >[color=green]
          >> However one guess would be that you need
          >>
          >> v3t0 * 5.0[/color]
          >
          > Darn close! v3t0 * 5.0f
          >[color=green]
          >> assuming the v3t0 is of type Vector3<double> because C++ will not deduce
          >> the T is double from the first argument, only from the second, and since
          >> you provided an int, it then looking for Vector3<int> as the first
          >> argument.[/color]
          >
          > That can't be exactly what's happening because it fails with both prefix
          > and
          > postfix operator*(); I think the answer to my problem is to explicitly
          > cast
          > the scaler operands to T. I.e., v3t0 * T(5);
          >[/color]

          Yes I got that wrong. Template argument deduction is happening on both
          parameters. But in the case of v3t0 * 5 you are giving contradictory
          information, the first arg says T is float, the second says it's an int.

          The best answer is as Victor says, use two template parameters so the
          template argument deduction is independent on both parameters to operator*.

          john


          Comment

          • Steven T. Hatton

            #6
            Re: overloading template operator arguments?

            Victor Bazarov wrote:
            [color=blue]
            > Steven T. Hatton wrote:[color=green]
            >> [...]
            >> template<typena me T>
            >> //Vect<T> operator*(const double& n, const Vect<T>& v)
            >> Vect<T> operator*(const T& n, const Vect<T>& v)
            >> {
            >> Vect<T> t(v);
            >> return t *= n;
            >> }[/color]
            >
            > Try
            >
            > template<class T, class U> Vect<U> operator *(T t, const Vect<U>& v)
            > {
            > Vect<U> vv(v);
            > return vv *= t;
            > }
            >[color=green]
            >> [..][/color]
            >
            > V[/color]
            Thanks! Works like a charm! :)
            --
            "If our hypothesis is about anything and not about some one or more
            particular things, then our deductions constitute mathematics. Thus
            mathematics may be defined as the subject in which we never know what we
            are talking about, nor whether what we are saying is true." - Bertrand
            Russell

            Comment

            Working...