473,569 Members | 2,729 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Linking static const class members?

Sorry about the big code dump. I tried to get it down to the minimum
required to demonstrate the problem. Although this is all done with GNU, I
believe the problem I'm having may be more general. Someone on the SuSE
programming mailing list suggested my problem is that I'm trying to execute
a function (I assume he meant the constructor) at compile time. The same
source code compile if I don't try to split it up into separate libraries.

On the following source code I run:

aclocal # sets up some kind of m4 macro magic.
autoheader # does wonderful things with my headers
autoconf # read the configure.ac and spit out a configure script
automake -a -c --gnits # generate Makefile.in's from Makefile.am's
./configure # read Makefile.in's and generate Makefiles
make # run make, duh!

with the results shown at the end of the code listing. The problem seems
to be related to my using static const class members. Other similarly
configured programs work OK. Can someone please explain why this won't
compile?

./configure.ac
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)
AC_INIT(testlib s, 0.1, ha*****@here.co m)
AC_CONFIG_SRCDI R([main.cpp])
AC_CONFIG_HEADE R([config.h])

AM_INIT_AUTOMAK E
# Checks for programs.
AC_PROG_CXX
AC_PROG_CC

# Checks for libraries.
AC_PROG_RANLIB
# Checks for header files.

# Checks for typedefs, structures, and compiler characteristics .
AC_C_CONST
AC_C_INLINE

# Checks for library functions.

AC_CONFIG_FILES ([Makefile
sth/Makefile
sth/util/Makefile])
AC_OUTPUT

./Makefile.am
INCLUDES = -I$(top_srcdir)/sth $(all_includes)
bin_PROGRAMS = testlibs
testlibs_SOURCE S = main.cpp
testlibs_LDFLAG S = $(all_libraries )
testlibs_LDADD = $(top_builddir)/sth/libsth.a
SUBDIRS = sth

./main.cpp
#include "ColorTest. h"
#include <iostream>

int main(int argc, char* argv[]) {
using sth::ColorTest;
ColorTest* ct = new ColorTest(std:: cout);
}

./sth/Makefile.am
INCLUDES = -I$(top_srcdir)/sth/util $(all_includes)
SUBDIRS = util
lib_LIBRARIES = libsth.a
libsth_a_LIBADD = $(top_builddir)/sth/util/libutil.a
noinst_HEADERS = ColorTest.h
libsth_a_SOURCE S = ColorTest.cpp
./sth/ColorTest.h
#ifndef STHCOLORTEST_H
#define STHCOLORTEST_H

#include <ostream>
namespace sth {
class ColorTest {
public:
ColorTest(std:: ostream& out);
~ColorTest();
};
};

#endif
./sth/ColorTest.cpp
#include "ColorTest. h"
#include <iostream>

int main(int argc, char* argv[]) {
using sth::ColorTest;
ColorTest* ct = new ColorTest(std:: cout);
}

./sth/util/Makefile.am
INCLUDES = -I$(all_includes )
lib_LIBRARIES = libutil.a
noinst_HEADERS = RgbColor.h Printable_IF.h
libutil_a_SOURC ES = RgbColor.cpp
./sth/util/RgbColor.h
#ifndef UTILRGBCOLOR_H
#define UTILRGBCOLOR_H

#include "Printable_IF.h "
namespace sth
{
namespace util
{

/**
@author Steven T. Hatton
*/

class RgbColor
: public Printable_IF
{
public:
RgbColor(const unsigned char& r=255,
const unsigned char& g=127,
const unsigned char& b=127);

unsigned char R() const;
void R(const unsigned char& r);

unsigned char G() const;
void G(const unsigned char& g);

unsigned char B() const;
void B(const unsigned char& b);

std::ostream& print(std::ostr eam& out) const;

static const RgbColor RED;
static const RgbColor GREEN;
static const RgbColor BLUE;
static const RgbColor BLACK;
static const RgbColor WHITE;
static const RgbColor MAGENTA;
static const RgbColor CYAN;
static const RgbColor YELLOW;
private:
unsigned char m_r;
unsigned char m_g;
unsigned char m_b;
};

inline unsigned char RgbColor::R() const
{
return m_r;
}
inline void RgbColor::R(con st unsigned char& r)
{
m_r = r;
}

inline unsigned char RgbColor::G() const
{
return m_g;
}

inline void RgbColor::G(con st unsigned char& g)
{
m_g = g;
}

inline unsigned char RgbColor::B() const
{
return m_b;
}

inline void RgbColor::B(con st unsigned char& b)
{
m_b = b;
}
}
}
#endif

./sth/util/RgbColor.h
#include "RgbColor.h "
namespace sth
{
util::RgbColor: :RgbColor(const unsigned char& r,
const unsigned char& g,
const unsigned char& b)
: m_r(r)
, m_g(g)
, m_b(b)
{}

const util::RgbColor util::RgbColor: :RED = util::RgbColor( 255,0,0);
const util::RgbColor util::RgbColor: :GREEN = util::RgbColor( 0,255,0);
const util::RgbColor util::RgbColor: :BLUE = util::RgbColor( 0,0,255);
const util::RgbColor util::RgbColor: :BLACK = util::RgbColor( 0,0,0);
const util::RgbColor util::RgbColor: :WHITE =
util::RgbColor( 255,255,255);
const util::RgbColor util::RgbColor: :MAGENTA = util::RgbColor( 255,0,255);
const util::RgbColor util::RgbColor: :CYAN = util::RgbColor( 0,255,255);
const util::RgbColor util::RgbColor: :YELLOW = util::RgbColor( 255,255,0);

/*!
\fn util::RgbColor: :print(std::ost ream& out) const
*/
std::ostream& util::RgbColor: :print(std::ost ream& out) const
{
out
<< "util::RgbColor ::{r=" << this->m_r
<< ",g=" << this->m_g
<< ",b=" << this->m_b << "}\n";
return out;
}

}

./sth/util/Printable_IF.h
#ifndef PRINTABLE_IF_H
#define PRINTABLE_IF_H
#include <iostream>
namespace sth
{
namespace util
{
class Printable_IF
{
public:
Printable_IF()
{}
virtual ~Printable_IF()
{}

virtual std::ostream& print(std::ostr eam& out) const = 0;
};

inline std::ostream& operator<<(std: :ostream& out, const Printable_IF&
pif)
{
return pif.print(out);
}
}
}
#endif

undefined reference to `sth::util::Rgb Color::RED'
./sth/libsth.a(ColorT est.o)(.text+0x 6f):./sth/ColorTest.cpp:9 : undefined
reference to `sth::util::Rgb Color::RED'
./sth/libsth.a(ColorT est.o)(.text+0x 77):./sth/ColorTest.cpp:9 : undefined
reference to `sth::util::Rgb Color::RED'
./sth/libsth.a(ColorT est.o)(.text+0x 81):./sth/ColorTest.cpp:9 : undefined
reference to `vtable for sth::util::RgbC olor'
./sth/libsth.a(ColorT est.o)(.text+0x 8f): In function
`sth::ColorTest ::ColorTest[in-charge](std::basic_ost ream<char,
std::char_trait s<char> >&)':

--
"[M]y dislike for the preprocessor is well known. Cpp is essential in C
programming, and still important in conventional C++ implementations , but
it is a hack, and so are most of the techniques that rely on it. ...I think
the time has come to be serious about macro-free C++ programming." - B. S.

Jul 22 '05 #1
3 2221
"Steven T. Hatton" <su******@setid ava.kushan.aa> wrote in message
news:fa******** ************@sp eakeasy.net...
Sorry about the big code dump. I tried to get it down to the minimum
required to demonstrate the problem. Although this is all done with GNU, I believe the problem I'm having may be more general. Someone on the SuSE
programming mailing list suggested my problem is that I'm trying to execute a function (I assume he meant the constructor) at compile time. The same
source code compile if I don't try to split it up into separate libraries.

On the following source code I run:
We don't need all that 'make' stuff.

[snip]
./main.cpp
#include "ColorTest. h"
#include <iostream>

int main(int argc, char* argv[]) {
using sth::ColorTest;
ColorTest* ct = new ColorTest(std:: cout);
You really should 'delete' your 'ColorTest' object
before terminating.
}
[snip more 'make' stuff]

More below.
./sth/ColorTest.h
#ifndef STHCOLORTEST_H
#define STHCOLORTEST_H

#include <ostream>
namespace sth {
class ColorTest {
public:
ColorTest(std:: ostream& out);
~ColorTest();
};
};

#endif
./sth/ColorTest.cpp
#include "ColorTest. h"
#include <iostream>

int main(int argc, char* argv[]) {
using sth::ColorTest;
ColorTest* ct = new ColorTest(std:: cout);
}
[snip more 'make' stuff]

More below.
./sth/util/RgbColor.h
#ifndef UTILRGBCOLOR_H
#define UTILRGBCOLOR_H

#include "Printable_IF.h "
namespace sth
{
namespace util
{

/**
@author Steven T. Hatton
*/

class RgbColor
: public Printable_IF
{
public:
RgbColor(const unsigned char& r=255,
const unsigned char& g=127,
const unsigned char& b=127);
I'd use symbolic names for those hard-coded numbers, in
a central place.

More below.

unsigned char R() const;
void R(const unsigned char& r);

unsigned char G() const;
void G(const unsigned char& g);

unsigned char B() const;
void B(const unsigned char& b);

std::ostream& print(std::ostr eam& out) const;

static const RgbColor RED;
static const RgbColor GREEN;
static const RgbColor BLUE;
static const RgbColor BLACK;
static const RgbColor WHITE;
static const RgbColor MAGENTA;
static const RgbColor CYAN;
static const RgbColor YELLOW;
Here's the real trouble.

This is in the middle of the definition of type 'RgbColor'.
But you're trying to define data members of this type.
Since at this point, 'RgbColor' is not completely defined,
You Can't Do That. You're trying to make a type contain
itself. That makes no sense. What are the names 'RED',
'GREEN', etc. really supposed to represent? Perhaps you
want an enumeration here.

More below.
private:
unsigned char m_r;
unsigned char m_g;
unsigned char m_b;
};

inline unsigned char RgbColor::R() const
{
return m_r;
}
inline void RgbColor::R(con st unsigned char& r)
{
m_r = r;
}

inline unsigned char RgbColor::G() const
{
return m_g;
}

inline void RgbColor::G(con st unsigned char& g)
{
m_g = g;
}

inline unsigned char RgbColor::B() const
{
return m_b;
}

inline void RgbColor::B(con st unsigned char& b)
{
m_b = b;
}
}
}
#endif

./sth/util/RgbColor.h
#include "RgbColor.h "
namespace sth
{
util::RgbColor: :RgbColor(const unsigned char& r,
const unsigned char& g,
const unsigned char& b)
: m_r(r)
, m_g(g)
, m_b(b)
{}

const util::RgbColor util::RgbColor: :RED = util::RgbColor( 255,0,0);


What is this supposed to be? It's not a valid declaration or definition.
Ask yourself:

What type of object am I declaring here?
What is the identifier for this object?

[snip the rest]

-Mike
Jul 22 '05 #2
Mike Wahler wrote:
"Steven T. Hatton" <su******@setid ava.kushan.aa> wrote in message
On the following source code I run:
We don't need all that 'make' stuff.


It's the only way I know of to clearly explain what I'm trying to
accomplish. The problem is not with the C++ code in the sense of syntax or
semantic violations. It is valid C++
int main(int argc, char* argv[]) {
using sth::ColorTest;
ColorTest* ct = new ColorTest(std:: cout);


You really should 'delete' your 'ColorTest' object
before terminating.
}
Since the code was only written for the purpose of isolating the problem, it
really isn't that important. And I really don't see the advantage in
deleting it before termination unless there are side-effect resulting from
the deletion which would impact the next run of the program, or some system
resources. That isn't the case here.
[snip more 'make' stuff] I'd use symbolic names for those hard-coded numbers, in
a central place.


What's a good symbolic name that means the maximum value of a range of
values between 0 and 255? How 'bout half that?
static const RgbColor RED;
static const RgbColor GREEN;
static const RgbColor BLUE;
static const RgbColor BLACK;
static const RgbColor WHITE;
static const RgbColor MAGENTA;
static const RgbColor CYAN;
static const RgbColor YELLOW;


Here's the real trouble.

This is in the middle of the definition of type 'RgbColor'.
But you're trying to define data members of this type.


No, those are declarations not definitions.
const util::RgbColor util::RgbColor: :RED =
util::RgbColor( 255,0,0);


What is this supposed to be? It's not a valid declaration or definition.
Ask yourself:

What type of object am I declaring here?
What is the identifier for this object?


It is of type const sth::util::RgbC olor. The fully qualified identifier is
sth::util::RgbC olor::RED. This is the ONLY correct syntax for initializing
const static members of non-integral type.

But the code doesn't link when compiled in a separate library from the code
using it.

The following describes everything I did to the source to get the output
displayed at the end. You may notice that I did make one minor adjustment
to the code to make the output a bit more coherent.

mkdir -p ../flatlibs/src
cd ../flatlibs
cp ../testlibs/src/sth/util/Printable_IF.h src
cp ../testlibs/src/sth/util/RgbColor.h src
cp ../testlibs/src/sth/util/RgbColor.cpp src
cp ../testlibs/src/sth/ColorTest.h src
cp ../testlibs/src/sth/ColorTest.cpp src
cp ../testlibs/src/main.cpp src

#Makefile.am
SUBDIRS = src
#EOF

#src/Makefile.am
bin_PROGRAMS = flatlibs
flatlibs_SOURCE S = \
ColorTest.cpp\
RgbColor.cpp\
main.cpp

noinst_HEADERS = \
ColorTest.h\
Printable_IF.h\
RgbColor.h
# EOF

autoscan
mv configure.scan configure.ac

# configure.ac
AC_PREREQ(2.59)
#modify the next line
AC_INIT(flatlib s, 0.1, bu**@insects.an t)
AC_CONFIG_SRCDI R([src/RgbColor.cpp])
AC_CONFIG_HEADE R([config.h])
#add next line by hand
AM_INIT_AUTOMAK E
AC_PROG_CXX
AC_PROG_CC
AC_C_CONST
AC_C_INLINE
AC_CONFIG_FILES ([Makefile
src/Makefile])
AC_OUTPUT
#EOF

aclocal
autoheader
autoconf
touch INSTALL NEWS README AUTHORS ChangeLog COPYING THANKS
automake -a -c --gnits
../configure
make
../src/flatlibs
util::RgbColor: :{r=255,g=0,b=0 }
--
"[M]y dislike for the preprocessor is well known. Cpp is essential in C
programming, and still important in conventional C++ implementations , but
it is a hack, and so are most of the techniques that rely on it. ...I think
the time has come to be serious about macro-free C++ programming." - B. S.

Jul 22 '05 #3
Mike Wahler wrote:
"Steven T. Hatton" <su******@setid ava.kushan.aa> wrote in message
news:fa******** ************@sp eakeasy.net...
Sorry about the big code dump. I tried to get it down to the minimum
required to demonstrate the problem. Although this is all done with GNU,

I
believe the problem I'm having may be more general. Someone on the SuSE
programming mailing list suggested my problem is that I'm trying to

execute
a function (I assume he meant the constructor) at compile time. The same
source code compile if I don't try to split it up into separate
libraries.

On the following source code I run:


We don't need all that 'make' stuff.

[snip]

const util::RgbColor util::RgbColor: :RED =
util::RgbColor( 255,0,0);


What is this supposed to be? It's not a valid declaration or definition.
Ask yourself:

What type of object am I declaring here?
What is the identifier for this object?

[snip the rest]

-Mike


I was able to reproduce the problem with Boost.Build. I finally figured out
what was wrong. It was just missing a link rule in one of the
Makefile.am's.
--
"[M]y dislike for the preprocessor is well known. Cpp is essential in C
programming, and still important in conventional C++ implementations , but
it is a hack, and so are most of the techniques that rely on it. ...I think
the time has come to be serious about macro-free C++ programming." - B. S.

Jul 22 '05 #4

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

Similar topics

5
2052
by: Thomas Matthews | last post by:
Hi, I have three classes: Category Author Publisher Each of these classes stores its information into a database table of <ID, text>. (They are fields that have a foreign key.) There is only one table for each instance of these classes (IOW,
3
3587
by: DanielBradley | last post by:
Hello all, I have recently been porting code from Linux to cygwin and came across a problem with static const class members (discussed below). I am seeking to determine whether I am programming non-standard C++ or if the problem lies elsewhere. To summarize static const class members are not being accessed properly when accessed from a...
18
5740
by: Erik Arner | last post by:
Hi, I really need some help here. After upgrading to g++ 3.4 I have run into all sorts of troubles that I'm sure depends on my lack of proper understanding of C++. I would now like to get it right once and for all, if possible. Most severe is the problem illustrated by the code below. It's based on the "pluggable factory pattern" described...
1
2339
by: Old Wolf | last post by:
I tried this code: #include <iostream> #include <string> template<typename T> struct enum_properties { static const long max; static const std::string name;
8
2028
by: Srini | last post by:
Hello all, I was just wondering about this. A const member function guarantees constness of the object within the function body. But there's no way for a member function to guarantee the constness of static members. Is there a way to do that? Also, is there a way for a static member function to guarantee constness of static members? TIA...
4
6397
by: Sanjay Kumar | last post by:
Folks ! I am working with VC++ after a long time and having problem linking latest xerces 2.7 in VC++ 2005 Express Edition. I have done following: 1. downloaded and unpacked the the library: http://www.apache.org/dist/xml/xerces-c/binaries/xerces-c_2_7_0-windows_2000-msvc_60.zip
0
2547
by: Philip Lowman | last post by:
I am in the process of trying to migrate a couple of build solutions to Visual Studio Express 2005 from VS 2003 Professional and I am running into a weird C/C++ runtime library linking issue when using the /MT compilation option. Our debug solution's /MTd flag works fine and using /MD also seems to work ok. For some reason I can't fathom,...
8
2879
by: crjjrc | last post by:
Hi, I've got a base class and some derived classes that look something like this: class Base { public: int getType() { return type; } private: static const int type = 0; };
4
5806
by: aaragon | last post by:
Hi everyone, I have a linking error when using gcc4.2 and static member variables. The class template definition is something around the following: template<> class Element<L2_t: public Element_common<L2, Side<2,2 { public:
0
7612
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8119
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 tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7668
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 Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
6281
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, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
5218
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3637
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2111
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1209
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
0
936
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating...

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.