#include <iostream>
#include <map>
#include <utility>
//
// Base
// / | \
// Derived1 Derived2 \
// \ | /
// Derived3
//
template< typename _T >
struct Base {
friend void * operator new ( size_t _size ){
std::cout << typeid( _T ).name() << std::endl;
return malloc( _size );
}
};
struct Derived1 : Base< Derived1 {
};
struct Derived2 : Base< Derived2 >{
};
struct Derived3 : Derived1, Derived2, Base< Derived3 >{
};
int main(){
Derived1 * d1 = new Derived1; // prints 8Derived3
Derived2 * d2 = new Derived2; // prints 8Derived3
} 9 2020
I am sorry, with copy/paste I clear message
May anyony explain me how `operator new' templates argument is deduced
as Derived3?
"wo****@gmail.com" <wo****@gmail.comkirjutas:
#include <iostream>
#include <map>
#include <utility>
//
// Base
// / | \
// Derived1 Derived2 \
// \ | /
// Derived3
//
template< typename _T >
Undefined behavior, you are not allowed to use such identifiers in your
code (beginning underscore followed by a capital letter). However, this
is probably not the reason of your concern.
struct Base {
friend void * operator new ( size_t _size ){
std::cout << typeid( _T ).name() << std::endl;
As far as I understand, operator new cannot be a template, and a friend
declaration does not make it into a template automatically anyway, so the
_T symbol should not be visible inside the function. If the compiler
still compiles this, I think this is a compiler bug.
return malloc( _size );
}
};
struct Derived1 : Base< Derived1 {
};
struct Derived2 : Base< Derived2 >{
};
struct Derived3 : Derived1, Derived2, Base< Derived3 >{
};
int main(){
Derived1 * d1 = new Derived1; // prints 8Derived3
Derived2 * d2 = new Derived2; // prints 8Derived3
}
You have provided illegal source to the compiler; the results can be
whatever. I am not sure if the compiler is obliged to produce a
diagnostic; I suspect it is. Maybe you should file a bug report to the
compiler provider.
Regards
Paavo
Paavo Helde wrote:
"wo****@gmail.com" <wo****@gmail.comkirjutas:
>template< typename _T >
Undefined behavior, you are not allowed to use such identifiers in your
code (beginning underscore followed by a capital letter). However, this
is probably not the reason of your concern.
I thought identifiers could start with underscore (or even be
underscore), why is it undefined?
--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
Daniel Pitts <ne******************@virtualinfinity.netkirjuta s:
Paavo Helde wrote:
>"wo****@gmail.com" <wo****@gmail.comkirjutas:
>>template< typename _T >
Undefined behavior, you are not allowed to use such identifiers in your code (beginning underscore followed by a capital letter). However, this is probably not the reason of your concern.
I thought identifiers could start with underscore (or even be
underscore), why is it undefined?
<quote>
17.4.3.1.2 Global names
Certain sets of names and function signatures are always reserved to the
implementation:
— Each name that contains a double underscore (_ _) or begins with
an underscore followed by an uppercase letter (2.11) is reserved to the
implementation for any use.
— Each name that begins with an underscore is reserved to the
implementation for use as a name in the global namespace.
</quote>
Cheers
Paavo
On 2008-06-14 22:28, Daniel Pitts wrote:
Paavo Helde wrote:
>"wo****@gmail.com" <wo****@gmail.comkirjutas:
>>template< typename _T >
Undefined behavior, you are not allowed to use such identifiers in your code (beginning underscore followed by a capital letter). However, this is probably not the reason of your concern.
I thought identifiers could start with underscore (or even be
underscore), why is it undefined?
Identifiers starting with an underscore followed by a capital letter are
reserved for the implementation, also identifiers in the global
namespace beginning with an underscore are also reserved (so you can
only use them inside functions, classes, and namespaces.
--
Erik Wikström
Daniel Pitts <ne******************@virtualinfinity.netkirjuta s:
Paavo Helde wrote:
>"wo****@gmail.com" <wo****@gmail.comkirjutas:
>>template< typename _T >
Undefined behavior, you are not allowed to use such identifiers in your code (beginning underscore followed by a capital letter). However, this is probably not the reason of your concern.
I thought identifiers could start with underscore (or even be
underscore), why is it undefined?
Sorry, did not actually answer the "why" question. The reason AFAIK is
that several implementation-defined preprocessor macros and compiler
extensions as well as all template definitions in the standard library
have to be implemented in header files (in the absent of 'export' at
least) and must somehow avoid conflicts with user-defined symbols. If
you are using Microsoft VC++, try for example:
#define _Bx 0
#include <string>
or
double _MSC_VER=-149.0;
Regards
Paavo
On Jun 14, 9:36 pm, Paavo Helde <nob...@ebi.eewrote:
"wo3...@gmail.com" <wo3...@gmail.comkirjutas:
#include <iostream>
#include <map>
#include <utility>
//
// Base
// / | \
// Derived1 Derived2 \
// \ | /
// Derived3
//
template< typename _T >
struct Base {
friend void * operator new ( size_t _size ){
std::cout << typeid( _T ).name() << std::endl;
As far as I understand, operator new cannot be a template, and
a friend declaration does not make it into a template
automatically anyway, so the _T symbol should not be visible
inside the function. If the compiler still compiles this, I
think this is a compiler bug.
The whole thing is fishy. This basically says that 1) the
global operator new is a friend of Base, and 2) provides an
implementation of the global operator new. Which is, I guess,
legal. Once... because this is a template, it's going to
provide a new implementation of the global operator new each
time the template is instantiated. Which is a violation of the
one definition rule, and so undefined behavior. (Since the
function is defined *in* the template, I'm pretty sure that the
use of _T is legal.)
There's also the problem that because the function is defined in
a class definition, it is inline; the global operator new
function is not allowed to be inline (for the obvious reason
that it's likely to have been used in some library code
somewhere, and that code won't see your inline definition).
return malloc( _size );
Which creates a couple of additional problems: if malloc fails,
his operator new is going to return a null pointer, rather than
raising a bad_alloc exception. And he hasn't provided a
corresponding operator delete (and of course, he has no idea as
to how the standard operator delete will try to free the
memory).
}
};
struct Derived1 : Base< Derived1 {
};
struct Derived2 : Base< Derived2 >{
};
struct Derived3 : Derived1, Derived2, Base< Derived3 >{
};
Note that the code doesn't correspond to the diagram in comments
at the top.
int main(){
Derived1 * d1 = new Derived1; // prints 8Derived3
Derived2 * d2 = new Derived2; // prints 8Derived3
}
You have provided illegal source to the compiler; the results
can be whatever. I am not sure if the compiler is obliged to
produce a diagnostic; I suspect it is. Maybe you should file a
bug report to the compiler provider.
It's undefined behavior, but I can guess what is happening.
He's instantiated the template three times, which provides three
different implementations of the global operator new. The
compiler just happened to use the last one it saw.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
James Kanze <ja*********@gmail.comkirjutas:
On Jun 14, 9:36 pm, Paavo Helde <nob...@ebi.eewrote:
>"wo3...@gmail.com" <wo3...@gmail.comkirjutas:
#include <iostream>
#include <map>
#include <utility>
//
// Base
// / | \
// Derived1 Derived2 \
// \ | /
// Derived3
//
template< typename _T >
struct Base {
friend void * operator new ( size_t _size ){
std::cout << typeid( _T ).name() << std::endl;
>As far as I understand, operator new cannot be a template, and a friend declaration does not make it into a template automatically anyway, so the _T symbol should not be visible inside the function. If the compiler still compiles this, I think this is a compiler bug.
The whole thing is fishy. This basically says that 1) the
global operator new is a friend of Base, and 2) provides an
implementation of the global operator new. Which is, I guess,
legal. Once... because this is a template, it's going to
provide a new implementation of the global operator new each
time the template is instantiated. Which is a violation of the
one definition rule, and so undefined behavior. (Since the
function is defined *in* the template, I'm pretty sure that the
use of _T is legal.)
Yes, I somehow assumed that the definition of the friend function should
not depend on whether it is "inline" in the friend declaration or not.
And if it is not, then _T can't be visible in the function body. And _T
is not participating in the function signature, so it would be impossible
to forward this to the non-inline non-template function definition.
right?
But anyway, as Comeau online does not complain about use of _T (renamed
to T to be sure), it seems my assumption was wrong. So the meaning of the
function body can differ depending on if it is defined inline in the
friend declaration, or separately. You learn something new every day...
>
There's also the problem that because the function is defined in
a class definition, it is inline; the global operator new
function is not allowed to be inline (for the obvious reason
that it's likely to have been used in some library code
somewhere, and that code won't see your inline definition).
[...]
>
struct Derived1 : Base< Derived1 {
};
struct Derived2 : Base< Derived2 >{
};
struct Derived3 : Derived1, Derived2, Base< Derived3 >{
};
Note that the code doesn't correspond to the diagram in comments
at the top.
How is that? I can't see anything wrong here.
>
int main(){
Derived1 * d1 = new Derived1; // prints 8Derived3
Derived2 * d2 = new Derived2; // prints 8Derived3
}
>You have provided illegal source to the compiler; the results can be whatever. I am not sure if the compiler is obliged to produce a diagnostic; I suspect it is. Maybe you should file a bug report to the compiler provider.
It's undefined behavior, but I can guess what is happening.
He's instantiated the template three times, which provides three
different implementations of the global operator new. The
compiler just happened to use the last one it saw.
Yes, you are right, this appears to be what gcc is doing. It seems VC++
9.0 detects the multiple definitions error:
error C2084: function 'void *Base<T>::operator new(size_t)' already has a
body
It seems Comeau online has the same opinion:
"ComeauTest.c", line 15: error: function "operator new(size_t)" has
already been
defined
friend void * operator new ( size_t _size ){
^
detected during instantiation of class "Base<T[with
T=Derived2]"
(In addition to mention an error regarding the incompatible throw
specification).
Thanks, and regards
Paavo
On Jun 15, 9:24 pm, Paavo Helde <nob...@ebi.eewrote:
James Kanze <james.ka...@gmail.comkirjutas:
On Jun 14, 9:36 pm, Paavo Helde <nob...@ebi.eewrote:
"wo3...@gmail.com" <wo3...@gmail.comkirjutas:
#include <iostream>
#include <map>
#include <utility>
//
// Base
// / | \
// Derived1 Derived2 \
// \ | /
// Derived3
//
template< typename _T >
struct Base {
friend void * operator new ( size_t _size ){
std::cout << typeid( _T ).name() << std::endl;
As far as I understand, operator new cannot be a template, and
a friend declaration does not make it into a template
automatically anyway, so the _T symbol should not be visible
inside the function. If the compiler still compiles this, I
think this is a compiler bug.
The whole thing is fishy. This basically says that 1) the
global operator new is a friend of Base, and 2) provides an
implementation of the global operator new. Which is, I guess,
legal. Once... because this is a template, it's going to
provide a new implementation of the global operator new each
time the template is instantiated. Which is a violation of the
one definition rule, and so undefined behavior. (Since the
function is defined *in* the template, I'm pretty sure that the
use of _T is legal.)
Yes, I somehow assumed that the definition of the friend function should
not depend on whether it is "inline" in the friend declaration or not.
And if it is not, then _T can't be visible in the function body. And _T
is not participating in the function signature, so it would be impossible
to forward this to the non-inline non-template function definition.
right?
But anyway, as Comeau online does not complain about use of _T (renamed
to T to be sure), it seems my assumption was wrong. So the meaning of the
function body can differ depending on if it is defined inline in the
friend declaration, or separately. You learn something new every day...
What's legal in the inline definition of a friend doesn't depend
on the signature of the friend. And things like:
template< typename Derived >
class ArithmeticOperators
{
friend Derived
operator+( Derived const& lhs, Derived const& rhs )
{
Derived result( lhs ) ;
result += rhs ;
return result ;
}
// ...
} ;
Are more or less standard practice, and have been since Barton
and Nackman invented the idiom (or even before that, if they
learned it from somewhere else). (In this case, of course,
there's no problem with the one definition rule, because each
instantiation of ArithmeticOperators will define a different
operator+.)
[...]
struct Derived1 : Base< Derived1 {
};
struct Derived2 : Base< Derived2 >{
};
struct Derived3 : Derived1, Derived2, Base< Derived3 >{
};
Note that the code doesn't correspond to the diagram in comments
at the top.
How is that? I can't see anything wrong here.
His diagram is:
Base
/ | \
Derived1 Derived2 \
\ | /
Derived3
His code implements:
Base Base
| |
Derived1 Derived2 Base
\ | /
Derived3
Not at all the same thing.
int main(){
Derived1 * d1 = new Derived1; // prints 8Derived3
Derived2 * d2 = new Derived2; // prints 8Derived3
}
You have provided illegal source to the compiler; the results
can be whatever. I am not sure if the compiler is obliged to
produce a diagnostic; I suspect it is. Maybe you should file a
bug report to the compiler provider.
It's undefined behavior, but I can guess what is happening.
He's instantiated the template three times, which provides three
different implementations of the global operator new. The
compiler just happened to use the last one it saw.
Yes, you are right, this appears to be what gcc is doing. It
seems VC++ 9.0 detects the multiple definitions error:
error C2084: function 'void *Base<T>::operator new(size_t)' already has a
body
It seems Comeau online has the same opinion:
"ComeauTest.c", line 15: error: function "operator new(size_t)" has
already been
defined
friend void * operator new ( size_t _size ){
^
detected during instantiation of class "Base<T[with
T=Derived2]"
(In addition to mention an error regarding the incompatible throw
specification).
Well, formally, it's undefined behavior (I think), so g++ isn't
wrong. But frankly, in this case, I'd expect an error message
as well.
--
James Kanze (GABI Software) email:ja*********@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Bonzo |
last post by:
I'm trying to write a class for a smart pointer. I'm having a problem
though when trying to implement operator== with both sides being a Smart.
(Or any function that I try to bring U into.)
The...
|
by: Christophe Barbe |
last post by:
I am not clear about friend functions of a template class.
GCC (3.3.2) wants me to add <> after the friend function names in the
class declaration and VisualC++ doesn't like that.
template...
|
by: Christophe Barbe |
last post by:
I posted a few days ago about the same problem but was not very clear. So
here is my second take at it.
Basically with GCC 3.3.2, I can't compile the example from the
C++ FAQ Lite available...
|
by: Yoon-Soo Lee |
last post by:
I am using Visual C++ .NET 2003 and running into some linking error from the
following template code.
The error messages is
error LNK2019: unresolved external symbol "class...
|
by: Ben Ingram |
last post by:
Hi all,
I am writing a template matrix class in which the template parameters are
the number of rows and number of columns. There are a number of reasons
why this is an appropriate tradeoff for...
|
by: Adam Parkin |
last post by:
Hello, all I'm having a problem with friend functions in a templatized Queue
class I'm writing using linked lists. The problem is that I can't get the
friend function to be able to access private...
|
by: Ruben Campos |
last post by:
Some questions about this code:
template <typename T> class MyTemplate;
template <typename T> MyTemplate <T> operator- (const MyTemplate <T> &
object);
template <typename T> MyTemplate <T>...
|
by: Amadeus W. M. |
last post by:
What is the difference between
friend ostream & operator<<(ostream & OUT, const Foo & f){
// output f
return OUT;
}
and
template <class X>
|
by: fdmfdmfdm |
last post by:
I have the following code:
#include <iostream>
#include <cstdlib>
#include <cassert>
using namespace std;
template <class T>
class Stack{
public:
enum{DefaultStack = 10, EmptyStack = -1};
|
by: lllomh |
last post by:
Define the method first
this.state = {
buttonBackgroundColor: 'green',
isBlinking: false, // A new status is added to identify whether the button is blinking or not
}
autoStart=()=>{
|
by: Aliciasmith |
last post by:
In an age dominated by smartphones, having a mobile app for your business is no longer an option; it's a necessity. Whether you're a startup or an established enterprise, finding the right mobile app...
|
by: giovanniandrean |
last post by:
The energy model is structured as follows and uses excel sheets to give input data:
1-Utility.py contains all the functions needed to calculate the variables and other minor things (mentions...
|
by: Teri B |
last post by:
Hi, I have created a sub-form Roles. In my course form the user selects the roles assigned to the course.
0ne-to-many. One course many roles.
Then I created a report based on the Course form and...
|
by: isladogs |
last post by:
The next Access Europe meeting will be on Wednesday 1 Nov 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM)
Please note that the UK and Europe revert to winter time on...
|
by: nia12 |
last post by:
Hi there,
I am very new to Access so apologies if any of this is obvious/not clear.
I am creating a data collection tool for health care employees to complete. It consists of a number of...
|
by: NeoPa |
last post by:
Introduction
For this article I'll be focusing on the Report (clsReport) class. This simply handles making the calling Form invisible until all of the Reports opened by it have been closed, when it...
|
by: isladogs |
last post by:
The next online meeting of the Access Europe User Group will be on Wednesday 6 Dec 2023 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM).
In this month's session, Mike...
|
by: GKJR |
last post by:
Does anyone have a recommendation to build a standalone application to replace an Access database? I have my bookkeeping software I developed in Access that I would like to make available to other...
| |