Question

chong kyong kim on Tue, 11 Nov 2014 16:07:29


Hi Igor and everyone
My knowledge of template is from reading tutorials. The program below
looks quite advanced. Could you please give me websites addresses that cover
the stuff below.
Thanks
Chong
***********************************************************************
template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete t;
 }

//template <typename _T, void (_destroyer)(_T*)>
template <typename _T, void (_destroyer)(_T*)>
 class Destroyer
 {
 };


template <
  typename _T,
  bool THREAD_SAFE = false,
  void (_destroyer)(_T*) = del_destroyer<_T>,
  template<typename _U, void (_destroyer2)(_U*)> class _DestroyerPolicy =
  Destroyer
 class Hook
 {

};

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Sponsored



Replies

Barry-Schwarz on Tue, 11 Nov 2014 16:36:18


Have you tried to google for C++ template tutorials

chong kyong kim on Tue, 11 Nov 2014 19:48:58


Hi Barry
I spent an hour and half through Google for C++ template tutorial
but just couldn't find a relevant one to answer my question. So
let me start one step at a time. Could you please tell me why the
following program below causes a compiler error.
Regards
Chong
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++=====
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <time.h>
#include <windows.h>
#include <winbase.h>
using namespace std;

template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete t;
 }

//template <typename _T, void (_destroyer)(_T*)>
template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>>
 class Destroyer
 {
  public:
 char *m;
  Destroyer(){m = new char[30]; strcpy_s(m,30,"chong kim");}
  void (_destroyer)(_T*);
  //void del_destroyer(_T *m);
  void Display(){printf("%s\n",m);}
};

 int main()
 {
  Destroyer<char,del_destroyer> Y;
  //Destroyer<char,_destroyer> Y;//gives a compiler error

   Y.Display();
   Y._destroyer(Y.m);
   //Y.del_destroyer<char>(Y.m);
  Y.Display();

 }
 
1>ConsoleApplication3.obj : error LNK2019: unresolved external symbol "public: void __thiscall Destroyer<char,&void __cdecl del_destroyer<char>(char *)>::_destroyer(char *)" (?_destroyer@?$Destroyer@D$1??$del_destroyer@D@@YAXPAD@Z@@QAEXPAD@Z) referenced in function _main
1>C:\Users\chong_2\Documents\My Document(FD1)\temp\C++exercise\ConsoleApplication3\Debug\ConsoleApplication3.exe : fatal error LNK1120: 1 unresolved externals


Igor Tandetnik on Tue, 11 Nov 2014 22:18:57


Could you please tell me why the following program below causes a compiler error.

This program is ill-formed - it's illegal for a class template to declare a member with the same name as a template parameter. GCC and CLang report this error correctly.

VC compiler does not. Instead, it reports a linker error - most likely, due to the compiler bug that I've discussed in the thread where you apparently copied this code from, namely

https://social.msdn.microsoft.com/Forums/en-US/87f017e2-1a0e-44df-95c4-8e0ed46542c6

(note that the code in that thread does not have a member with the same name as a  template parameter - you've added that one on your own).

chong kyong kim on Wed, 12 Nov 2014 00:53:27


Hi Igor
I know that my program is a mess and I don't know where
the problems are. The class Destroyer below does not have
a member whose name is the same as a template parametter.
Nevertheless it won't compile.

Thanks

Chong

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <time.h>
#include <windows.h>
#include <winbase.h>
using namespace std;

template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete []t;t=NULL;printf("2  %s\n",t);
 }

//template <typename _T, void (_destroyer)(_T*)>
template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>>
 class Destroyer
 {
  public:
 char *m;
  Destroyer(){m = new char[30]; strcpy_s(m,30,"chong kim");}
  void destroy(_T*){_destroyer(_T*);}//syntax error: ')'
  //void destroy(_T*){del_destroyer<_T>;}
  void Display(){printf("%s\n",m);}
};

 int main()
 {
  Destroyer<char,del_destroyer<char>> Y;

 //Destroyer<char,_destroyer> Y;//a compilation error

  Y.Display();
  Y.destroy(Y.m);

  Y.Display();// why not NULL or garbage printout?

 }

Igor Tandetnik on Wed, 12 Nov 2014 01:06:55



  void destroy(_T*){_destroyer(_T*);}//syntax error: ')'

You seem to be trying to call a function, but you write a type where a parameter is supposed to be. You probably mean something like " void destroy(_T* p){ _destroyer(p); } "

chong kyong kim on Wed, 12 Nov 2014 01:38:47


Thanks Igor

Why does the line below give compiler error?

int main()

{

Destroyer<char,_destroyer> Y;//error :'_destroyer' is undefined

}

Thanks

Chong

Igor Tandetnik on Wed, 12 Nov 2014 01:54:58


Because the name "_destroyer" is undefined here. What entity is it supposed to refer to, in your opinion?

chong kyong kim on Wed, 12 Nov 2014 02:01:50


Hi Igor

Because "template <tyname..,void (_destroyer)(_T*) = del_destroyer<_T>>" , I imagined '_destroyer's definition was the same as that of 'del_destroyer'.

Regards

Chong


Igor Tandetnik on Wed, 12 Nov 2014 02:15:32


_destroyer is a template parameter. It's only meaningful within the template of which it is a parameter. Just like a function parameter is only meaningful within that function.

chong kyong kim on Wed, 12 Nov 2014 02:29:27


Hi Igor

So _destroyer in "void (_destroyer)(_T*) = del_destroyer<_T>>" is only meaningful within the template where it is a parameter. How about the following two lines? The first one compiles but the 2nd doesn't. Is it because '_destroyer' is meaningful only in the template?

 Destroyer<char,del_destroyer<char>> Y;

Destroyer<char,_destroyer> Y;//a compilation error

Thanks

Chong

Igor Tandetnik on Wed, 12 Nov 2014 02:34:20


You are asking the same question a second time. The answer hasn't changed in the past half hour.

chong kyong kim on Wed, 12 Nov 2014 02:49:51


Hi Igor

Many thanks for helping me. It is late and I need to get some sleep. I would need to ask you some more questions tomorrow. Good night!

Regards

Chong

chong kyong kim on Wed, 12 Nov 2014 13:45:04


Hi Igor
The following program below does not compile. Can you please tell me how
to fix it.
Regards
Chong

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <windows.h>
#include <winbase.h>
using namespace std;

template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete []t;t=NULL;printf("2  %s\n",t);
 }

template <class T> //forward reference
class Destroyer;

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,class tmpClass=Destroyer>
//template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,template<typename _U,
// void (_destroyer)(_U*)> class tmpClass=Destroyer>
class Destroyer
{
 public:
  char *m;
  Destroyer(){m = new char[30]; strcpy_s(m,30,"chong kim");}
  void destroy(_T* p){_destroyer(p);}// it's illegal for a
      //class template to declare a member with the same
      //name as a template parameter.
  void tmpDestroyer(){ tmpClass tmp; tmp.Display(); tmp.destroy(tmp.m);}
  void Display(){printf("%s\n",m);}
};

 int main()
 {
      Destroyer<char,del_destroyer<char>,Destroyer<char>> Y;//compiler error
      //Destroyer<char,del_destroyer<char>> Y;//compiler error-specialised template?

      Y.Display();
      Y.tmpDestroyer();
      Y.destroy(Y.m);
      Y.tmpDestroyer();
      Y.Display();//NULL and garbage printout.

      return 0;
 }

1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(30): error C2977: 'Destroyer' : too many template arguments
1>          c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(21) : see declaration of 'Destroyer'
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(42): error C2059: syntax error : '}'
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(58): fatal error C1075: end of file found before the left angle-bracket '<' at 'c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(34)' was matched

Igor Tandetnik on Wed, 12 Nov 2014 14:33:24


On 11/12/2014 8:45 AM, "chong kyong kim" wrote:

template <class T> //forward reference
class Destroyer;

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,class tmpClass=Destroyer>
class Destroyer

You attempt to declare class template Destroyer twice - once with one parameter, and again with three. The two declarations should agree.

       Destroyer<char,del_destroyer<char>,Destroyer<char>> Y;//compiler error

Which compiler version are you using? With older compilers, you need to add a space between two closing angle brackets, otherwise they are interpreted as a shift operator >>

chong kyong kim on Wed, 12 Nov 2014 18:36:40


Hi Igor
I have modified the program as below. There is now only one version of
Destroyer. It still fails to compile. Can you please tell me how to fix
it. I gave a space between >>.  I use VC++2012.
Regards
Chong

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <windows.h>
#include <winbase.h>
using namespace std;

template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete []t;t=NULL;printf("2  %s\n",t);
 }

template <class T> //forward reference
class Destroyer;


template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T> >
class Destroyer2
 {
  public:
 char *m;
  Destroyer2(){m = new char[30]; strcpy_s(m,30,"mother kim");}
  void destroy(_T* p){_destroyer(p);}
  void Display(){printf("%s\n",m);}
};

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,class tmpClass=Destroyer2>
//template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,template<typename _U,
//void (_destroyer)(_U*)> class tmpClass=Destroyer2>
 class Destroyer
 {
  public:
 char *m;
  Destroyer(){m = new char[30]; strcpy_s(m,30,"chong kim");}
  void destroy(_T* p){_destroyer(p);}// it's illegal for a
      //class template to declare a member with the same
      //name as a template parameter.
  void tmpDestroyer(){ tmpClass<char,del_destroyer<char> > tmp; tmp.Display(); tmp.destroy(tmp.m);}
  void Display(){printf("%s\n",m);}
};

 int main()
 {
     Destroyer<char,del_destroyer<char>,Destroyer2<char,del_destroyer<char> > > Y;//compiler error

     Y.Display();
     Y.tmpDestroyer();
     Y.destroy(Y.m);
     Y.tmpDestroyer();
     Y.Display();//NULL and garbage printout.

     return 0;
 }
/*
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(41): error C2977: 'Destroyer' : too many template arguments
1>          c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(32) : see declaration of 'Destroyer'
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(45): error C2079: 'Y' uses undefined class 'Destroyer'
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(48): error C2228: left of '.Display' must have class/struct/union
 */

Igor Tandetnik on Wed, 12 Nov 2014 18:42:13


You still forward-declare Destroyer with one template parameter, then define it with three.

chong kyong kim on Wed, 12 Nov 2014 19:06:42


Hi Igor.

I removed the forward reference. I get the following compiler error:

+++++++++++++++++++++++++++++++++++++++++++

1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(39): error C2143: syntax error : missing ';' before '<'
1>          c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(39) : while compiling class template member function 'void Destroyer<_T,_destroyer,tmpClass>::tmpDestroyer(void)'
1>          with
1>          [
1>              _T=char,
1>              _destroyer=void del_destroyer<char>(char *),
1>              tmpClass=Destroyer2<char,void del_destroyer<char>(char *)>
1>          ]
1>          c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(48) : see reference to function template instantiation 'void Destroyer<_T,_destroyer,tmpClass>::tmpDestroyer(void)' being compiled
1>          with
1>          [
1>              _T=char,
1>              _destroyer=void del_destroyer<char>(char *),
1>              tmpClass=Destroyer2<char,void del_destroyer<char>(char *)>
1>          ]
1>          c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(45) : see reference to class template instantiation 'Destroyer<_T,_destroyer,tmpClass>' being compiled
1>          with
1>          [
1>              _T=char,
1>              _destroyer=void del_destroyer<char>(char *),
1>              tmpClass=Destroyer2<char,void del_destroyer<char>(char *)>
1>          ]
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(39): error C2065: 'tmp' : undeclared identifier
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(39): error C2228: left of '.Display' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(39): error C2228: left of '.destroy' must have class/struct/union
1>          type is ''unknown-type''
1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(39): error C2228: left of '.m' must have class/struct/union
1>          type is ''unknown-type''

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Regards

Chong

Igor Tandetnik on Wed, 12 Nov 2014 20:20:23


tmpClass is not a template, yet you are trying to supply template parameters for it.

chong kyong kim on Wed, 12 Nov 2014 21:03:31


Hi Igor

Thanks for your help. Doesn't "class tmpClass=Destroyer2" mean that tmpClass is a template since Destroyer2 is a template.

Regards

Chong

Igor Tandetnik on Wed, 12 Nov 2014 21:10:07



Thanks for your help. Doesn't "class tmpClass=Destroyer2" mean that tmpClass is a template since Destroyer2 is a template.

No, it means that your program is ill-formed and will fail to compile, as it tries to specify a class template as a default argument for a regular (non-template) parameter.

chong kyong kim on Wed, 12 Nov 2014 21:30:33


Hi Igor

My program, although it is a mess, compiles and runs successfully. Many thanks again.

Regards

Chong

chong kyong kim on Wed, 12 Nov 2014 22:23:46


Hi Igor

Is there any way to make tmpClass a template?

Regards

Chong

Igor Tandetnik on Wed, 12 Nov 2014 22:33:36



Is there any way to make tmpClass a template?

You have it this way, in the commented-out section of code.

chong kyong kim on Wed, 12 Nov 2014 23:04:05


Hi Igor
I have modified the program as below. It does not compile. Have I missed
anything?
Regards
Chong

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <windows.h>
#include <winbase.h>
using namespace std;

template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete []t;t=NULL;printf("2  %s\n",t);
 }

//template <class T> //forward reference - don't want 2 versions of Destroyer
//class Destroyer;

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T> >
class Destroyer2
 {
  public:
 char *m;
  Destroyer2(){m = new char[30]; strcpy_s(m,30,"mother kim");}
  void destroy(_T* p){_destroyer(p);}
  void Display(){printf("%s\n",m);}
};

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,template<typename _U,
void (_destroyer2)(_U*)> class tmpClass=Destroyer2>
 class Destroyer
 {
 public:
  char *m;
  Destroyer(){m = new char[30]; strcpy_s(m,30,"chong kim");}
  void destroy(_T* p){_destroyer(p);}// it's illegal for a
      //class template to declare a member with the same
      //name as a template parameter.
  void tmpDestroyer(){ tmpClass<char,_destroyer<char>> tmp; tmp.Display();    tmp.destroy(tmp.m);}
                      //'tmpClass' is a template
  void Display(){printf("%s\n",m);}
};

 int main()
 {
  //The following line gives a compiler error!
  Destroyer<char,del_destroyer<char>,Destroyer2<char,del_destroyer<char>>>  Y;

  Y.Display();
  Y.tmpDestroyer();
  Y.destroy(Y.m);
  Y.tmpDestroyer();
  Y.Display();//NULL and garbage printout.

  return 0;
 }


Igor Tandetnik on Wed, 12 Nov 2014 23:15:56


In this line:

void tmpDestroyer(){ tmpClass<char,_destroyer<char>> tmp; tmp.Display();

you are trying to pass a template parameter <char> to _destroyer, but _destroyer is not a template.

In this line:

Destroyer<char,del_destroyer<char>,Destroyer2<char,del_destroyer<char>>>

you are passing a class as the last parameter to Destroyer<>, but it expects a class template.

chong kyong kim on Thu, 13 Nov 2014 15:16:09


Hi Igor
I have modified the program as below. Have I done as you instructed? What is _destroyer if is not a template?
Regards
Chong

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,
template<typename _U,void (_destroyer2)(_U*)> class tmpClass=Destroyer2>
 class Destroyer
 {
  public:
 char *m;
  Destroyer(){m = new char[30]; strcpy_s(m,30,"chong kim");}
  void destroy(_T* p){_destroyer(p);}// it's illegal for a
      //class template to declare a member with the same
      //name as a template parameter.
  void tmpDestroyer(){tmpClass<char,_destroyer> tmp; tmp.Display(); tmp.destroy(tmp.m);}
  //void tmpDestroyer(){tmpClass<char,del_destroyer<char>> tmp; tmp.Display(); tmp.destroy(tmp.m);}
                      //'tmpClass' is a template
  void Display(){printf("%s\n",m);}
};

 int main()
 {
  Destroyer<char,del_destroyer<char>,Destroyer2>  Y;
  //Destroyer<char,_destroyer<char>,Destroyer2<char,_destroyer<char> > >  Y;//
  //compiler error - see example 2.

  Y.Display();
  Y.tmpDestroyer();
  Y.destroy(Y.m);
  Y.tmpDestroyer();
  Y.Display();//NULL and garbage printout.

 }


1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(30): error C3201: the template parameter list for class template 'Destroyer2' does not match the template parameter list for template parameter 'tmpClass'

1>c:\users\chong_2\documents\my document(fd1)\temp\c++exercise\consoleapplication3\consoleapplication3.cpp(48): error C3201: the template parameter list for class template 'Destroyer2' does not match the template parameter list for template parameter 'tmpClass'

Igor Tandetnik on Thu, 13 Nov 2014 16:08:24


On 11/13/2014 10:16 AM, "chong kyong kim" wrote:

I have modified the program as below. Have I done as you instructed?

I don't recall giving you any instructions.

What is _destroyer if is not a template?

It's a non-type template parameter, of function type.

   Y.destroy(Y.m);
   Y.Display();//NULL and garbage printout.

Y.Display() tries to use Y.m, but the memory to which Y.m points to has been previously deallocated (via a call to Y.destroy(Y.m) which ultimately ends up running "delete[] Y.m"). This leaves Y.m a dangling pointer, and dereferencing it inside Y.Display() exhibits undefined behavior.

chong kyong kim on Thu, 13 Nov 2014 16:19:42


Hi Igor

So what should I do about "tmpClass<char,_destroyer)"? Why do I get a compiler error that the parameter list of Destroyer doesn't match that of tmpClass?

Regards

Chong

Igor Tandetnik on Thu, 13 Nov 2014 17:58:14


On 11/13/2014 11:19 AM, "chong kyong kim" wrote:

So what should I do about "tmpClass<char,_destroyer)"? Why do I get a compiler error that the parameter list of Destroyer doesn't match that of tmpClass?

Now that you got substantially back to the code you started with (one from

https://social.msdn.microsoft.com/Forums/en-US/87f017e2-1a0e-44df-95c4-8e0ed46542c6

), you are seeing the same compiler bug that the OP in that thread is seeing.

chong kyong kim on Thu, 13 Nov 2014 18:16:47


Hi Igor
Could you do me a big favour please. Could you compile my program under your GCC
please. Hope it compiles in GCC! If it does, I know that I've done everything
right.
Regards
Chong

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#include "stdafx.h"
#include <stdio.h>
#include <string>
#include <windows.h>
#include <winbase.h>
using namespace std;

template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete []t;t=NULL;printf("2  %s\n",t);
 }

//template <class T> //forward reference - don't want 2 versions of Destroyer
//class Destroyer;


template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T> >
class Destroyer2
 {
  public:
 char *m;
  Destroyer2(){m = new char[30]; strcpy_s(m,30,"mother kim");}
  void destroy(_T* p){_destroyer(p);}
  void Display(){printf("%s\n",m);}
};

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,template<typename _U,void (_destroyer2)(_U*)> class tmpClass=Destroyer2>
 class Destroyer
 {
  public:
  char *m;
  Destroyer(){m = new char[30]; strcpy_s(m,30,"chong kim");}
  void destroy(_T* p){_destroyer(p);}// it's illegal for a
      //class template to declare a member with the same
      //name as a template parameter.
  void tmpDestroyer(){tmpClass<char,_destroyer> tmp; tmp.Display(); tmp.destroy(tmp.m);
                     }//?? - Is this ok?!
                      //'tmpClass' is a template
  void Display(){printf("%s\n",m);}
};

 int main()
 {
  Destroyer<char,del_destroyer<char>,Destroyer2>  Y;
  //Destroyer<char,_destroyer<char>,Destroyer2<char,_destroyer<char> > >  Y;//
  //compiler error - see example 2.

  Y.Display();
  Y.tmpDestroyer();
   Y.destroy(Y.m);
  Y.tmpDestroyer();
  Y.Display();//NULL and garbage printout - undefined behaviour!

 }

davewilk on Thu, 13 Nov 2014 21:42:47


Hi Igor
Could you do me a big favour please. Could you compile my program under your GCC
please. Hope it compiles in GCC! If it does, I know that I've done everything
right.

You can do it yourself here:

http://rextester.com/runcode

But you will need to get rid of Windows-specific code.


David Wilkinson | Visual C++ MVP


chong kyong kim on Thu, 13 Nov 2014 23:34:55


Hi Dave

Thanks. My program compiles and runs in c++ gcc.

Regards

Chong


chong kyong kim on Fri, 14 Nov 2014 17:25:55


Hi Igor  and David
The following program below compiles and runs. But I've got questions.
In [Q1] below, why does "tmpClass<_T,_destroyer<_T*>>" cause a compiler error?
It is ok with "tmpClass<_T, del_destroyer<_T>>".
Regards
Chong

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
c.f. This compiles and runs in C++ gcc, not in VC++

#include <stdio.h>
#include <string.h>

template <typename T>
 inline
 void del_destroyer(T *t)
 {
  delete []t;t=NULL;printf("2  %s\n",t);
 }

//template <class T> //forward reference - don't want 2 versions of Destroyer
//class Destroyer;

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T> >
//What is _destroyer if is not a template? It's a non-type template
//parameter, of function type.
class Destroyer2
{
  public:
  char *m;
  Destroyer2(){m = new char[30]; strcpy(m,"mother kim");}
  void destroy(_T* p){_destroyer(p);}
  void Display(){printf("%s\n",m);}
};

template <typename _T, void (_destroyer)(_T*) = del_destroyer<_T>,
   template<typename _U,void (_destroyer2)(_U*)> class tmpClass=Destroyer2>
class Destroyer
{
  public:
  char *m;
  Destroyer(){m = new char[30]; strcpy(m,"chong kim");}
  void destroy(_T* p){_destroyer(p);}// it's illegal for a
      //class template to declare a member with the same
      //name as a template parameter.
//[Q 1]
        void tmpDestroyer(){tmpClass<_T,_destroyer> tmp; tmp.Display();
                             tmp.destroy(tmp.m);}
                      //'tmpClass' is a template
  void Display(){printf("%s\n",m);}
};

int main()
{
  Destroyer<char,del_destroyer,Destroyer2> Y;
  //Destroyer<char,del_destroyer<char>,Destroyer2>  Y;//ok!
  //Destroyer<char,_destroyer<char>,Destroyer2<char,_destroyer<char> > > Y;//
  //compiler error - see example 2 (i.e. _destroyer is a template parameter,
         //an undefined identifier, defined and meaningful only in the template).

  Y.Display();
  Y.tmpDestroyer();
         Y.destroy(Y.m);
  Y.tmpDestroyer();
  Y.Display();//NULL and garbage printout.

  return 0;
}


Igor Tandetnik on Fri, 14 Nov 2014 18:52:30


On 11/14/2014 12:25 PM, "chong kyong kim" wrote:

In [Q1] below, why does "tmpClass<_T,_destroyer<_T*>>" cause a compiler error?
It is ok with "tmpClass<_T, del_destroyer<_T>>".

We've been through this before. _destroyer is not a template, and so it's meaningless to try and give it template parameters. On the other hand, del_destroyer is a template.

chong kyong kim on Fri, 14 Nov 2014 23:31:05


Hi Igor

so "tmpClass<_T,_destroyer>" is equal to "tmpClass<_T, del_destroyer>" and "tmpClass<_T, del_destroyer(_T)"?

Regards

Chong

 

Igor Tandetnik on Sat, 15 Nov 2014 00:30:48


On 11/14/2014 6:31 PM, "chong kyong kim" wrote:

so "tmpClass<_T,_destroyer>" is equal to "tmpClass<_T, del_destroyer>" and "tmpClass<_T, del_destroyer(_T)"?

tmpClass<_T, del_destroyer> wouldn't compile, so no, it's not equivalent to the other two.

_destroyer is equivalent to whatever is specified as the second template parameter when instantiating Destroyer template. If the second parameter was del_destroyer<_T>, or was left unspecified so that it picked up its default value, then yes, tmpClass<_T,_destroyer> would be equivalent to tmpClass<_T, del_destroyer(_T). This is in fact the case in your example.

chong kyong kim on Sat, 15 Nov 2014 15:19:30


Hi Igor

In (Q1) "tmpClass <char, del_stroyer>" compiles and runs? Is it supposed not?

Regards

Chong

Igor Tandetnik on Sat, 15 Nov 2014 15:43:33


On 11/15/2014 10:19 AM, "chong kyong kim" wrote:

In (Q1) "tmpClass <char, del_stroyer>" compiles and runs? Is it supposed not?

It is supposed to. My bad. The compiler is able to perform template argument deduction, and determine that "del_destroyer" stands for "del_stroyer<char>" in this case.

chong kyong kim on Sat, 15 Nov 2014 16:15:57


Hi Igor

Can you give me an example of template parameter deduction please? When does it happen?

Regards
Chong

Igor Tandetnik on Sat, 15 Nov 2014 18:49:44


On 11/15/2014 11:15 AM, "chong kyong kim" wrote:

Can you give me an example of template parameter deduction please? When does it happen?

template <typename T>
void f(T x) {};

f(42);    // same as f<int>(42);

In the call "f(42)", the template parameter is deduced from the type of the argument (the literal 42 is of type int).

chong kyong kim on Wed, 19 Nov 2014 14:53:23


Hi Igor
When does template argument deduction apply? The following
program below is a rather silly question. I am a bit confused.
Regards
Chong
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#include <iostream>

template <typename T>
class Fn{
 public:
    Fn(T t){std::cout<<t<<"\n";}   
};

int main()
{

    //Fn<int> f(3);//Prints "3".
    Fn f(3);//error: missing template arguments for Fn - No template argument
            //deduction for Fn??
    std::cout << "Hello, world!\n";

    return 0;
}


davewilk on Wed, 19 Nov 2014 15:34:20


Hi Igor
When does template argument deduction apply? The following
program below is a rather silly question. I am a bit confused.
Regards
Chong
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

#include <iostream>

template <typename T>
class Fn{
 public:
    Fn(T t){std::cout<<t<<"\n";}   
};

int main()
{

    //Fn<int> f(3);//Prints "3".
    Fn f(3);//error: missing template arguments for Fn - No template argument
            //deduction for Fn??
    std::cout << "Hello, world!\n";

    return 0;
}

Template deduction works only for functions, not classes. So you can do

#include <iostream>

// non-templated class
class Fn
{
public:
    // templated constructor
    template <typename T> Fn(const T& t)
    {
        std::cout << t << "\n";
    }
};

int main()
{
    Fn f(3);
    std::cout << "Hello, world!\n";
}

chong kyong kim on Thu, 20 Nov 2014 19:21:06


Hi David

In your example code, I put "Fn<const int> f(3);" instead of "Fn f(3);" and it got me a compiler error: Fn is not a template (C++ gcc).

Regards

Chong

Igor Tandetnik on Thu, 20 Nov 2014 19:25:57


On 11/20/2014 2:21 PM, "chong kyong kim" wrote:

In your example code, I put "Fn<const int> f(3);" instead of "Fn f(3);" and it got me a compiler error: Fn is not a template (C++ gcc).

Is there a question in there somewhere? Yes, class Fn is not a template.

chong kyong kim on Thu, 20 Nov 2014 20:09:53


Hi Igor

I just wondered how the template deduction has taken place in "Fn f(3)". C++ gcc gets me compiler errors for "Fn<const int> f(3)" and "Fn f<const int>(3)". Is Fn a function template?

Regards

Chong

Igor Tandetnik on Thu, 20 Nov 2014 20:14:10


On 11/20/2014 3:09 PM, "chong kyong kim" wrote:

I just wondered how the template deduction has taken place in "Fn f(3)". C++ gcc gets me compiler errors for "Fn<const int> f(3)" and "Fn f<const int>(3)". Is Fn a function template?

Fn is a regular, non-template class, with a constructor that's a function template. There is no syntax to provide explicit template arguments to a templated constructor - it has no choice but to rely on template argument deduction.