Template virtual member method is not allowed. How to bypass that?

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

    #1

    Template virtual member method is not allowed. How to bypass that?

    =============== =============== ===========
    Windows 2000
    CYGWIN_NT-5.0 1.3.22(0.78/3/2)
    GNU gcc version 3.2 20020927 (prerelease)
    =============== =============== ===========


    Here is some program which is compiled and works fine.

    ############### ############### ##############
    ====== C++ code : File t1.cpp : BEGIN ======
    #include <iostream>
    using namespace std;

    class BBB
    {
    public :
    void foo1 (int n);

    protected :
    virtual void foo2(int n) = 0;
    };

    class DDD : public BBB
    {
    public :
    void foo2(int n);
    };

    void BBB::foo1 (int n)
    {
    cout << __PRETTY_FUNCTI ON__ << " : n = " << n << endl;
    foo2(n);
    }

    void DDD::foo2 (int n)
    {
    cout << __PRETTY_FUNCTI ON__ << " : n = " << n << endl;
    }


    int main ()
    {
    DDD d;
    d.foo1(123);
    return 0;
    }
    ====== C++ code : File t1.cpp : END ========


    ====== Compilation & Run : BEGIN ======

    $ g++ t1.cpp

    void BBB::foo1(int) : n = 123
    virtual void DDD::foo2(int) : n = 123

    ====== Compilation & Run : END ========



    I need something like with template virtual member method.
    But template virtual member method is not allowed.

    ############### ############### ##############
    ====== C++ code : File t2.cpp : BEGIN ======

    #include <iostream>
    using namespace std;

    class BBB
    {
    public :
    template <typename T>
    void foo1 (const T& t);

    protected :
    template <typename T>
    virtual void foo2(const T& t) = 0; // (Line#12) ILLEGAL because template virtual member method is not allowed
    };

    class DDD : public BBB
    {
    public :
    template <typename T>
    void foo2(const T& t);
    };

    template <typename T>
    void BBB::foo1 (const T& t)
    {
    cout << __PRETTY_FUNCTI ON__ << " : t = " << t << endl;
    foo2(t);
    }

    template <typename T>
    void DDD::foo2 (const T& t)
    {
    cout << __PRETTY_FUNCTI ON__ << " : t = " << t << endl;
    }


    int main ()
    {
    DDD d;
    d.foo1(123);
    return 0;
    }

    ====== C++ code : File t2.cpp : END ========


    ====== Compilation : BEGIN ======

    $ g++ t2.cpp

    t2.cpp:12: invalid use of `virtual' in template declaration of `virtual void
    BBB::foo2(const T&)'

    ====== Compilation : END ========


    Question.
    Is there any bypass to get what I want to ?


    Thanks,

    =============== =============== ============
    Alex Vinokur
    mailto:alexvn@c onnect.to
    Top 10 nền tảng affiliate network hoạt động hiệu quả nhất hiện nay. Tìm hiểu chuyên sâu về nền tảng tiếp thị liên kết, phân loại lợi ích, và các chiến lược tối ưu để thành công trong lĩnh vực affiliate.

    http://sourceforge.net/users/alexvn
    =============== =============== ============




  • Victor Bazarov

    #2
    Re: Template virtual member method is not allowed. How to bypass that?

    "Alex Vinokur" <alexvn@bigfoot .com> wrote...[color=blue]
    > [.. example of polymorphism in its simplest use..][/color]
    [color=blue]
    > I need something like with template virtual member method.[/color]

    Why do you think you need that?
    [color=blue]
    > But template virtual member method is not allowed.[/color]

    No, it's not. That's correct.
    [color=blue]
    >
    > ############### ############### ##############
    > ====== C++ code : File t2.cpp : BEGIN ======
    >
    > #include <iostream>
    > using namespace std;
    >
    > class BBB
    > {
    > public :
    > template <typename T>
    > void foo1 (const T& t);
    >
    > protected :
    > template <typename T>
    > virtual void foo2(const T& t) = 0; // (Line#12) ILLEGAL because[/color]
    template virtual member method is not allowed

    Yes. You probably want to make the entire class a template,
    or have a nested [helper] class, which should be a template.
    Template classes can have virtual functions.
    [color=blue]
    > };[/color]

    [...]
    [color=blue]
    > Question.
    > Is there any bypass to get what I want to ?[/color]

    No, there is no "bypass" of what is disallowed. But there are
    other ways. If you could just tell us what you need that for,
    perhaps we could suggest a solution. Try not to phrase your
    inquiries "the language doesn't let me do this, how do I do this?"

    Victor


    Comment

    • Alex Vinokur

      #3
      Re: Template virtual member method is not allowed. How to bypass that?


      "Victor Bazarov" <v.Abazarov@att Abi.com> wrote in message news:vh5v3e9hkk qjdf@corp.super news.com...[color=blue]
      > "Alex Vinokur" <alexvn@bigfoot .com> wrote...[color=green]
      > > [.. example of polymorphism in its simplest use..][/color]
      >[color=green]
      > > I need something like with template virtual member method.[/color]
      >
      > Why do you think you need that?
      >[color=green]
      > > But template virtual member method is not allowed.[/color]
      >
      > No, it's not. That's correct.
      >[color=green]
      > >
      > > ############### ############### ##############
      > > ====== C++ code : File t2.cpp : BEGIN ======
      > >
      > > #include <iostream>
      > > using namespace std;
      > >
      > > class BBB
      > > {
      > > public :
      > > template <typename T>
      > > void foo1 (const T& t);
      > >
      > > protected :
      > > template <typename T>
      > > virtual void foo2(const T& t) = 0; // (Line#12) ILLEGAL because[/color]
      > template virtual member method is not allowed
      >
      > Yes. You probably want to make the entire class a template,
      > or have a nested [helper] class, which should be a template.
      > Template classes can have virtual functions.
      >[color=green]
      > > };[/color]
      >
      > [...]
      >[color=green]
      > > Question.
      > > Is there any bypass to get what I want to ?[/color]
      >
      > No, there is no "bypass" of what is disallowed. But there are other ways.[/color]

      One of such ways are proposed below.
      Of course, this approach doesn't solve the problem of disallowance of template virtual member method.
      Perhaps it will be useful in certain situations.
      [color=blue]
      > If you could just tell us what you need that for,
      > perhaps we could suggest a solution. Try not to phrase your
      > inquiries "the language doesn't let me do this, how do I do this?"[/color]

      You are right. The wording is ambiguous.
      [color=blue]
      >
      > Victor
      >
      >[/color]

      =============== =============== =========
      GNU g++ version 3.3.1 (cygming special)
      =============== =============== =========


      ========= C++ code : File t.cpp : BEGIN =========
      #include <string>
      #include <sstream>
      #include <iostream>
      #include <iomanip>
      #include <map>
      #include <typeinfo>
      #include <assert.h>
      using namespace std;

      #ifdef __GNUC__
      #define FUNC_NAME __PRETTY_FUNCTI ON__
      #else
      #define FUNC_NAME ""
      #endif

      #define COUT \
      cout << "[ " \
      << __FILE__ \
      << ", #" \
      << setw(3) \
      << std::right \
      << __LINE__ \
      << " ] " \
      << FUNC_NAME \
      << " : "


      // ---------------------
      // ---------------------
      template <class To, class From>
      bool stream_cast (const From& from, To& to)
      {
      stringstream stream;
      stream << from;
      return (stream >> to);
      }


      // ---------------------
      struct AuxTypenames
      {
      friend bool operator< (const AuxTypenames& ins1_i, const AuxTypenames& ins2_i);

      string class_typename_ ;
      string arg_typename_;

      AuxTypenames (
      const string& class_typename_ i,
      const string& arg_typename_i
      )
      :
      class_typename_ (class_typename _i),
      arg_typename_ (arg_typename_i )
      {}
      };

      // ---------------------
      bool operator< (const AuxTypenames& ins1_i, const AuxTypenames& ins2_i)
      {
      if (ins1_i.class_t ypename_ < ins2_i.class_ty pename_) return true;
      if (ins1_i.class_t ypename_ > ins2_i.class_ty pename_) return false;

      return (ins1_i.arg_typ ename_ < ins2_i.arg_type name_);
      }



      // ---------------------
      // ---------------------
      class Boo;


      // ---------------------
      class AuxBaseCaller
      {
      public :
      virtual bool caller(Boo* ptr_io, const string& str_i) = 0;
      };


      template <typename T1, typename T2>
      class AuxCaller : public AuxBaseCaller
      {
      public :
      bool caller(Boo* ptr_io, const string& str_i);
      };



      // ---------------------
      template <typename T1, typename T2>
      bool AuxCaller<T1, T2>::caller(Boo * ptr_io, const string& str_i)
      {
      T2 data;

      if (!stream_cast (str_i, data))
      {
      COUT << "Unable to do stream_cast : "
      << typeid(str_i).n ame()
      << " to "
      << typeid(data).na me()
      << "; From-string-value = <"
      << str_i
      << ">"
      << endl;

      return false;
      }

      T1* ptr = dynamic_cast<T1 *> (ptr_io);
      assert (!(ptr == NULL));

      ptr->foo2 (data);

      return true;
      }


      // ---------------------
      // ---------------------
      class Boo
      {
      protected :
      void bridge (const string& arg_typename_i, const string& str_i);

      public :
      static map<AuxTypename s, AuxBaseCaller*> callers_s;

      virtual ~Boo () {}

      template <typename T>
      void foo1 (const T& t);

      };

      // ---------------------
      class Dxx : public Boo
      {
      template <typename T1, typename T2> friend class AuxCaller;

      private :
      template <typename T>
      void foo2(const T& t) { COUT << "t = " << t << endl; }
      };


      // ---------------------
      class Dyy : public Boo
      {
      template <typename T1, typename T2> friend class AuxCaller;

      private :
      template <typename T>
      void foo2(const T& t) { COUT << "t = " << t << endl; }
      };


      // ---------------------
      class Dzz : public Boo
      {
      template <typename T1, typename T2> friend class AuxCaller;

      private :
      template <typename T>
      void foo2(const T& t) { COUT << "t = " << t << endl; }
      };



      // ---------------------
      // ---------------------
      template <typename T>
      void Boo::foo1 (const T& data_i)
      {
      COUT << "data_i = " << data_i << endl;

      string str;
      if (!stream_cast (data_i, str))
      {
      COUT << "Unable to do stream_cast : "
      << typeid(data_i). name()
      << " to "
      << typeid(str).nam e()
      << "; From-T-value = <"
      << data_i
      << ">"
      << endl;

      return;
      }

      bridge(typeid(d ata_i).name(), str);
      }


      // ---------------------
      void Boo::bridge (const string& arg_typename_i, const string& str_i)
      {
      COUT << "arg_typena me_i = " << arg_typename_i << endl;

      assert (!callers_s.emp ty());
      const string class_typename (typeid(*this). name());
      const map<AuxTypename s, AuxBaseCaller*> ::const_iterato r find_iter = callers_s.find (AuxTypenames (class_typename , arg_typename_i) );

      if (find_iter == callers_s.end() )
      {
      COUT << ""
      << "Pair (class typename = "
      << class_typename
      << ", arg typename = "
      << arg_typename_i
      << ") is not allowed"
      << endl;
      return;
      }

      assert (find_iter != callers_s.end() );

      if (!find_iter->second->caller(this, str_i)) assert (0);

      }


      // ---------------------
      // ---------------------
      map<AuxTypename s, AuxBaseCaller*> Boo::callers_s;

      #define ADD_CALLER(T1, T2) \
      Boo::callers_s[AuxTypenames (typeid(T1).nam e(), typeid(T2).name ())] = \
      static_cast<Aux BaseCaller*> (new AuxCaller<T1, T2> ())


      // ---------------------
      int main ()
      {
      ADD_CALLER (Dxx, int);
      ADD_CALLER (Dxx, char);
      ADD_CALLER (Dxx, float);

      ADD_CALLER (Dyy, int);
      ADD_CALLER (Dyy, char);

      // ---------------------
      Dxx dxx;
      cout << endl;
      cout << endl;
      cout << "\t--- Dxx test ---" << endl;

      dxx.foo1(100);
      cout << endl;
      dxx.foo1(char(' a'));
      cout << endl;
      dxx.foo1(float (3.14));


      Dyy dyy;
      cout << endl;
      cout << endl;
      cout << "\t--- Dyy test ---" << endl;

      dyy.foo1(200);
      cout << endl;
      dyy.foo1(char(' b'));
      cout << endl;
      dyy.foo1(float (2.71));


      Dzz dzz;
      cout << endl;
      cout << endl;
      cout << "\t--- Dzz test ---" << endl;

      dzz.foo1(300);

      // -----
      return 0;
      }

      ========= C++ code : File t.cpp : END ===========

      Two remarks.
      1. stream_cast() was discussed by Dietmar Kuehl at


      2. To be sure the stream_cast conversion is bijective, one could use functions which detect stream_cast bijectivity




      ========= Compilation & Run : BEGIN =========

      $ g++ t.cpp

      $ a

      --- Dxx test ---
      [ t.cpp, #175 ] void Boo::foo1(const T&) [with T = int] : data_i = 100
      [ t.cpp, #199 ] void Boo::bridge(con st std::string&, const std::string&) : arg_typename_i = i
      [ t.cpp, #143 ] void Dxx::foo2(const T&) [with T = int] : t = 100

      [ t.cpp, #175 ] void Boo::foo1(const T&) [with T = char] : data_i = a
      [ t.cpp, #199 ] void Boo::bridge(con st std::string&, const std::string&) : arg_typename_i = c
      [ t.cpp, #143 ] void Dxx::foo2(const T&) [with T = char] : t = a

      [ t.cpp, #175 ] void Boo::foo1(const T&) [with T = float] : data_i = 3.14
      [ t.cpp, #199 ] void Boo::bridge(con st std::string&, const std::string&) : arg_typename_i = f
      [ t.cpp, #143 ] void Dxx::foo2(const T&) [with T = float] : t = 3.14


      --- Dyy test ---
      [ t.cpp, #175 ] void Boo::foo1(const T&) [with T = int] : data_i = 200
      [ t.cpp, #199 ] void Boo::bridge(con st std::string&, const std::string&) : arg_typename_i = i
      [ t.cpp, #154 ] void Dyy::foo2(const T&) [with T = int] : t = 200

      [ t.cpp, #175 ] void Boo::foo1(const T&) [with T = char] : data_i = b
      [ t.cpp, #199 ] void Boo::bridge(con st std::string&, const std::string&) : arg_typename_i = c
      [ t.cpp, #154 ] void Dyy::foo2(const T&) [with T = char] : t = b

      [ t.cpp, #175 ] void Boo::foo1(const T&) [with T = float] : data_i = 2.71
      [ t.cpp, #199 ] void Boo::bridge(con st std::string&, const std::string&) : arg_typename_i = f
      [ t.cpp, #207 ] void Boo::bridge(con st std::string&, const std::string&) : Pair (class typename = 3Dyy, arg typename = f) is not
      allowed


      --- Dzz test ---
      [ t.cpp, #175 ] void Boo::foo1(const T&) [with T = int] : data_i = 300
      [ t.cpp, #199 ] void Boo::bridge(con st std::string&, const std::string&) : arg_typename_i = i
      [ t.cpp, #207 ] void Boo::bridge(con st std::string&, const std::string&) : Pair (class typename = 3Dzz, arg typename = i) is not
      allowed

      ========= Compilation & Run : END ===========


      =============== =============== =======
      Alex Vinokur
      mailto:alexvn@c onnect.to

      =============== =============== =======




      Comment

      Working...