473,405 Members | 2,171 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Difference between inline initialization and definition.


I posted a gcc bug

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13332
here is the text:
-----------------------------------------------------------

This code will compile fine but fail on a linker error.

templ_examp.cpp:41: undefined reference to `Bounds<float,
(unsigned)4>::size'

However if "static const unsigned size" is changed from an "unsigned" to an
"int" or "short", it appears to work correctly.
template <typename T, unsigned N>
class Bounds
{
public:

static const unsigned size = N;
T * ptr;

T & operator[] ( unsigned i )
{
if ( i >= size )
{
throw "Array outa bounds";
}

return ptr[ i ];
}

Bounds( T ( & i_ptr)[N] )
: ptr( i_ptr )
{
}
};

template <typename T, unsigned N>
Bounds<T,N> make_bounds( T ( & i_ptr)[N] )
{
return Bounds<T,N>( i_ptr );
}
float array[] = { 1., 2., 3., 4. };

#include <iostream>

int main()
{

std::cout << make_bounds( array )[ 2 ];
std::cout << make_bounds( array ).size;
// std::cout << make_bounds( array )[ 20 ]; // throw exception
}
------- Additional Comment #1 From Andrew Pinski 2003-12-06 08:18
[reply] -------

From bug 13259 which this is bug is a dup of:
The standard says that you may inline-initialize the static variable,
but you still need to _define_ it somewhere so that a memory location
is assigned to it.

-----------------------------------------------------------

if below is not a definition:

....
static const unsigned size = N;
....

what is it ?

Jul 22 '05 #1
4 2144
Gianni Mariani wrote in news:bq********@dispatch.concentric.net:

I posted a gcc bug

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13332
here is the text:
-----------------------------------------------------------

This code will compile fine but fail on a linker error.

templ_examp.cpp:41: undefined reference to `Bounds<float,
(unsigned)4>::size'

However if "static const unsigned size" is changed from an "unsigned"
to an "int" or "short", it appears to work correctly.

Actually it works inspite of the fact your code is incorrect. I can't
remember wether a compiler is required to produce a diagnostic (an
error / warning meassage) when this rule is violated, but I think not.

template <typename T, unsigned N>
class Bounds
{
public:

static const unsigned size = N;
T * ptr;

T & operator[] ( unsigned i )
{
This usage of 'size' is not one where a compile-time constant is
required. (see below).

Note that when you change size to int or short, the comparison below
requires a conversion from (int or short) to unsigned. It would appear
that gcc "thinks" its easier to do this by converting the initializer (N)
directly (hence no linking). When size is unsigned gcc "thinks" a memory
reference would be better, so the linker discovers your incorrect code.

if ( i >= size )
{
throw "Array outa bounds";
}

return ptr[ i ];
}

Bounds( T ( & i_ptr)[N] )
: ptr( i_ptr )
{
}
};

template <typename T, unsigned N>
Bounds<T,N> make_bounds( T ( & i_ptr)[N] )
{
return Bounds<T,N>( i_ptr );
}
float array[] = { 1., 2., 3., 4. };

#include <iostream>

int main()
{

std::cout << make_bounds( array )[ 2 ];
std::cout << make_bounds( array ).size;
// std::cout << make_bounds( array )[ 20 ]; // throw exception
}
------- Additional Comment #1 From Andrew Pinski 2003-12-06 08:18
[reply] -------

From bug 13259 which this is bug is a dup of:
The standard says that you may inline-initialize the static variable,
but you still need to _define_ it somewhere so that a memory location
is assigned to it.

In other words it isn't a bug (in gcc).
-----------------------------------------------------------

if below is not a definition:

...
static const unsigned size = N;
...

what is it ?


Its a declaration and an intialization, but it is not a *definition*.

The value of this initialization can only be used where a compile-time
contexts is *required*, i.e. as an array bounds, as a template paramiter
etc. Otherwise a defenition is required.

The defenition should be like this:

template <typename T, unsigned N>
unsigned const Bounds< T, N >::size; /* no initializer */

Rob.
--
http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #2
Rob Williscroft wrote:
Gianni Mariani wrote in news:bq********@dispatch.concentric.net:
Its a declaration and an intialization, but it is not a *definition*.

The value of this initialization can only be used where a compile-time
contexts is *required*, i.e. as an array bounds, as a template paramiter
etc. Otherwise a defenition is required.

The defenition should be like this:

template <typename T, unsigned N>
unsigned const Bounds< T, N >::size; /* no initializer */


OK, I get it. Thanks for clearing that up.

However, I still don't get the reason for this. Is there a good reason
to be splitting hairs like this ? After all, the compiler can certainly
work out when a reference is needed or not. If it was uninitiialized, I
can imagine why one should have a declaration, but is seems very strange
to be able to initialize a variable an not declare it.

With C++, you learn somthing every day :-)

Jul 22 '05 #3
Gianni Mariani wrote in news:bq********@dispatch.concentric.net:
Rob Williscroft wrote:
Gianni Mariani wrote in news:bq********@dispatch.concentric.net:

Its a declaration and an intialization, but it is not a *definition*.

The value of this initialization can only be used where a
compile-time contexts is *required*, i.e. as an array bounds, as a
template paramiter etc. Otherwise a defenition is required.

The defenition should be like this:

template <typename T, unsigned N>
unsigned const Bounds< T, N >::size; /* no initializer */


OK, I get it. Thanks for clearing that up.

However, I still don't get the reason for this. Is there a good
reason to be splitting hairs like this ?


Not that I'm aware off, particularly as templates get "merged" all the
time.

The /bad/ reason is probably the comittee though 1 exception for
static integral constants was enough.
After all, the compiler can
certainly work out when a reference is needed or not. If it was
uninitiialized, I can imagine why one should have a declaration, but
is seems very strange to be able to initialize a variable an not
declare it.

With C++, you learn somthing every day :-)


Yup.

I thought of this workaround (assuming there's some good reason
for avoiding the *definition*), since you don't need a definition
if you avoid all non-compile-time contexts.

template < unsigned N > class whatever
{
static unsigned const size = N;
....
....
if (i < sizeof( char[ size ] )) ...

or:

....
enum {Size = size};
if (i < Size) ...
Maybe a member function would be better though:

static unsigned runtime_size()
{
return unsigned( sizeof( char[ size ] ));
}

Rob. -- http://www.victim-prime.dsl.pipex.com/
Jul 22 '05 #4
Rob Williscroft wrote:
Gianni Mariani wrote in news:bq********@dispatch.concentric.net: I thought of this workaround (assuming there's some good reason
for avoiding the *definition*), since you don't need a definition
if you avoid all non-compile-time contexts.

template < unsigned N > class whatever
{
static unsigned const size = N;
...
...
if (i < sizeof( char[ size ] )) ...

or:

...
enum {Size = size};
if (i < Size) ...
Maybe a member function would be better though:

static unsigned runtime_size()
{
return unsigned( sizeof( char[ size ] ));
}


This is cool ...

In this particular case though you could more simply write "return N".

I'm not too concerned about having to add a declaration, I'm more
concerned about the apparent violation of the "rule of least astonishment".


Jul 22 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

7
by: Senthilraja | last post by:
I have the following program using templates. Someone please let me know the syntax to be used for defining the member functions push, pop etc. as non-inline functions. #include <iostream>...
32
by: Mario Fratelli | last post by:
MyClass *p = new MyClass; MyClass *p = new MyClass(); do they mean something different? Thanks a lot, Mario Fratelli.
47
by: Richard Hayden | last post by:
Hi, I have the following code: /******************************** file1.c #include <iostream> extern void dummy(); inline int testfunc() {
20
by: Grumble | last post by:
Hello everyone, As far as I understand, the 'inline' keyword is a hint for the compiler to consider the function in question as a candidate for inlining, yes? What happens when a function with...
4
by: Aniruddha | last post by:
I want to initialize an array of function pointers (global) If I do it like: /* definition of foo_1, foo_2, foo_3 all return void and take no args */ void (* foo) (); foo = foo_1 ; foo = foo_2...
2
by: evan | last post by:
Hi, I've got an easy one... I need to inline a few functions from one module to another. By looking at the compiled code I can see that the function is inlined if it is called from within the...
9
by: Bilgehan.Balban | last post by:
Hi, If I define an inline function in one .c file, and use it from another, after compiling and linking the two, it seems the function is not inlined but rather called as a regular function. I...
23
by: Jess | last post by:
Hello, I understand the default-initialization happens if we don't initialize an object explicitly. I think for an object of a class type, the value is determined by the constructor, and for...
14
by: jg | last post by:
Does C++ standard require an inline function be generated all the time ? For example, #include <iostream> using namespace std; inline int foo() {
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.