473,703 Members | 2,657 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

'static const std::string' in a header file

Hello,

This thread follow my previous one on the gcc mailing list. Basically I
-still- have a problem in my code. I define in a header file:

static const std::string foo = "bar";

Which not only seems to be a bad practice but also creates a bug on
MacOSX panther (gcc 3.3).
Could someone suggest me a better approach than this one. Knowing that
I need to have a const reference access to the string.

I tried the approach :

// header.H
extern const std::string foo;

//implementation. C
const std::string foo = "bar";

but this doesn't seems to work with VS6/7: error LNK2019: unresolved
external symbol ...

---------
Gabriel Dos Reis (from the gcc ML) proposed the following approach:

// header.H
const std::string& foo();

// implementation. C
const std::string& foo() {
static const std::string instance = "foo";
return instance;
}

Comments/suggestions very welcome.
Thanks,
Mathieu
Jul 22 '05 #1
9 10266
Mathieu Malaterre wrote:
This thread follow my previous one on the gcc mailing list.
Basically I -still- have a problem in my code. I define in a header file:

static const std::string foo = "bar";

Which not only seems to be a bad practice but also creates a bug on
MacOSX panther (gcc 3.3).
Could someone suggest me a better approach than this one. Knowing
that I need to have a const reference access to the string.

I tried the approach :

// header.H
extern const std::string foo;

//implementation. C
const std::string foo = "bar";

but this doesn't seems to work with VS6/7: error LNK2019: unresolved
external symbol ...
That's rather strange. Are you sure you're linking all the necessary
modules together? Does your 'implementation .C' include 'header.H'? The
compiler needs to know that the 'foo' you define in 'implementation .C' is
the one other modules refer to. For that 'foo' must be declared 'extern'
as well. To fix that either include 'header.H' in 'implementation .C' or
change the statement in 'implementation .C' to read

extern const std::string foo = "bar";

---------
Gabriel Dos Reis (from the gcc ML) proposed the following approach:

// header.H
const std::string& foo();

// implementation. C
const std::string& foo() {
static const std::string instance = "foo";
return instance;
}


The biggest difference between this and the other approach is that 'foo'
here is "extern" by default because it's a function. For a const object
you must specify 'extern' yourself.

Victor
Jul 22 '05 #2
Victor Bazarov wrote:
Mathieu Malaterre wrote:
This thread follow my previous one on the gcc mailing list.
Basically I -still- have a problem in my code. I define in a header file:

static const std::string foo = "bar";

Which not only seems to be a bad practice but also creates a bug
on MacOSX panther (gcc 3.3).
Could someone suggest me a better approach than this one. Knowing
that I need to have a const reference access to the string.

I tried the approach :

// header.H
extern const std::string foo;

//implementation. C
const std::string foo = "bar";

but this doesn't seems to work with VS6/7: error LNK2019: unresolved
external symbol ...

That's rather strange. Are you sure you're linking all the necessary
modules together? Does your 'implementation .C' include 'header.H'? The
compiler needs to know that the 'foo' you define in 'implementation .C' is
the one other modules refer to. For that 'foo' must be declared 'extern'
as well. To fix that either include 'header.H' in 'implementation .C' or
change the statement in 'implementation .C' to read

extern const std::string foo = "bar";


Doesn't seems to make any change (*). The library is building fine
though. It's just that as soon as I build an executable that link to the
lib I get the error...

(*)
BuildUpDicomDir .cxx
Linking...
Creating library C:\Dashboards\M y
Tests\gdcmVS60\ bin\Debug/BuildUpDicomDir .lib and object C:\Dashboards\M y
Tests\gdcmVS60\ bin\Debug/BuildUpDicomDir .exp
BuildUpDicomDir .obj : error LNK2001: unresolved external symbol "class
std::basic_stri ng<char,struct std::char_trait s<char>,class
std::allocator< char> > const gdcm::GDCM_UNKN OWN"
(?GDCM_UNKNOWN@ gdcm@@3V?$basic _string@DU?$cha r_traits@D@std@ @V?$allocator@D @2@@std@@B)
C:\Dashboards\M y Tests\gdcmVS60\ bin\Debug/BuildUpDicomDir .exe : fatal
error LNK1120: 1 unresolved externals
Error executing link.exe.
Thanks,
Mathieu
Ps: I'll try the 'function' approach and let you know.

Jul 22 '05 #3
* Victor Bazarov:
To fix that either include 'header.H' in 'implementation .C' or
change the statement in 'implementation .C' to read

extern const std::string foo = "bar";


This will a generate multiple definition error when the header
is included in more than one compilation unit.

Instead just do

std::string const foo = "bar";

which, however, doesn't guarantee a single instance.

---------
Gabriel Dos Reis (from the gcc ML) proposed the following approach:

// header.H
const std::string& foo();

// implementation. C
const std::string& foo() {
static const std::string instance = "foo";
return instance;
}


That's one possible work-around if you want to be guaranteed _one_
and only one instance of the string, except you probably don't want
the implementation file compiled as 'C'. Nitpick: it will be more
efficient to place the instance outside the function. As it is
every function call has to check whether it's been constructed.

Another work-around is to use a template class.

#include <string>

struct Dummy {};
template<typena me T>
struct Strings_
{
static std::string const foo;
};
template<typena me T> std::string const Strings_<T>::fo o = "foo";
typedef Strings_<Dummy> Strings;

int main()
{
std::string s = Strings::foo;
}

That's more to write but most efficient in terms of generated code.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #4
Alf P. Steinbach wrote:
* Victor Bazarov:
To fix that either include 'header.H' in 'implementation .C' or
change the statement in 'implementation .C' to read ^^^^^^^^^^^^^^^ ^^^
extern const std::string foo = "bar";

This will a generate multiple definition error when the header
is included in more than one compilation unit.


No, it won't. If the statement in the _header_ does not have the
initialiser, and has the 'extern', then it's not a definition.

Instead just do

std::string const foo = "bar";

which, however, doesn't guarantee a single instance.
Exactly. So, don't.
[...]


Victor
Jul 22 '05 #5
* Victor Bazarov:
Alf P. Steinbach wrote:
* Victor Bazarov:
To fix that either include 'header.H' in 'implementation .C' or
change the statement in 'implementation .C' to read ^^^^^^^^^^^^^^^ ^^^
extern const std::string foo = "bar";

This will a generate multiple definition error when the header
is included in more than one compilation unit.


No, it won't. If the statement in the _header_ does not have the
initialiser, and has the 'extern', then it's not a definition.


Sorry, I misunderstood what you wrote.

Another way to achieve the same is to make sure the header file is
included in the implementation file.

I just assumed that and therefore misread what you wrote.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #6
BuildUpDicomDir .cxx
Linking...
Creating library C:\Dashboards\M y
Tests\gdcmVS60\ bin\Debug/BuildUpDicomDir .lib and object C:\Dashboards\M y
Tests\gdcmVS60\ bin\Debug/BuildUpDicomDir .exp
BuildUpDicomDir .obj : error LNK2001: unresolved external symbol "class
std::basic_stri ng<char,struct std::char_trait s<char>,class
std::allocator< char> > const gdcm::GDCM_UNKN OWN"
(?GDCM_UNKNOWN@ gdcm@@3V?$basic _string@DU?$cha r_traits@D@std@ @V?$allocator@D @2@@std@@B)

C:\Dashboards\M y Tests\gdcmVS60\ bin\Debug/BuildUpDicomDir .exe : fatal
error LNK1120: 1 unresolved externals
Error executing link.exe.


I am a complete moron I forgot about the __declspec( dllexport )

Sorry for the noise, and thanks for your help.

Mathieu

Jul 22 '05 #7
Another work-around is to use a template class.

#include <string>

struct Dummy {};
template<typena me T>
struct Strings_
{
static std::string const foo;
};
template<typena me T> std::string const Strings_<T>::fo o = "foo";
typedef Strings_<Dummy> Strings;

int main()
{
std::string s = Strings::foo;
}


That's the exact same problem. It doesn't work on MacOSX Panther because
of the way file-scope objects in dylibs get initialized.

Mathieu

Jul 22 '05 #8
* Mathieu Malaterre:
Another work-around is to use a template class.

#include <string>

struct Dummy {};
template<typena me T>
struct Strings_
{
static std::string const foo;
};
template<typena me T> std::string const Strings_<T>::fo o = "foo";
typedef Strings_<Dummy> Strings;

int main()
{
std::string s = Strings::foo;
}


That's the exact same problem. It doesn't work on MacOSX Panther because
of the way file-scope objects in dylibs get initialized.


Is Panther a C++ compiler in addition to being an operating system version?

If the above doesn't work then you have a non-comforming C++ implementation,
or you're doing something outside the scope of standard C++, or both.

Try to be more precise.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Jul 22 '05 #9
Alf P. Steinbach wrote:
* Mathieu Malaterre:
Another work-around is to use a template class.

#include <string>

struct Dummy {};
template<typena me T>
struct Strings_
{
static std::string const foo;
};
template<typena me T> std::string const Strings_<T>::fo o = "foo";
typedef Strings_<Dummy> Strings;

int main()
{
std::string s = Strings::foo;
}


That's the exact same problem. It doesn't work on MacOSX Panther because
of the way file-scope objects in dylibs get initialized.

Is Panther a C++ compiler in addition to being an operating system version?

If the above doesn't work then you have a non-comforming C++ implementation,
or you're doing something outside the scope of standard C++, or both.

Try to be more precise.


I am just quoting a mail from:

http://gcc.gnu.org/ml/gcc/2005-01/msg00505.html

This is completely out of my scope of expertise. I only know that you
have to be carefull with global object that doesn't gets properly
initialized before its first use. And Mac-O file format have a notion of
lazy data constructor.

That's all I know

Hope this answer your question,
Mathieu

Jul 22 '05 #10

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

Similar topics

3
2470
by: Old Wolf | last post by:
Hi all. G++ fails to compile the following: #include <string> int main() { std::string foo("abc=123"); std::string::const_iterator delimiter = std::find(foo.begin(), foo.end(), '=');
2
1798
by: Susan Baker | last post by:
Hi, I have declared a class MyClass in a header file MyClass.h I have then gone onto define the class in MyClass.cpp. This is (roughly) what the definition (.cpp) file looks like: #include "BaseHeader.h" /****************************************************/ /* Constructors/Destructor */
8
9189
by: Patrick Kowalzick | last post by:
Dear NG, I would like to change the allocator of e.g. all std::strings, without changing my code. Is there a portable solution to achieve this? The only nice solution I can think of, would be a namespace and another typedef to basic_string: namespace my_string {
2
1935
by: anelma via .NET 247 | last post by:
Following code works fine, when compiled with VS 6.0, but not anymore when compiled in .NET. What's wrong here, I can't see it by myself? arrString content will be garbage with .net compilation, but when compiled with 6.0 it contains string from Vector (that's how I want it to work). std::vector<std::string> Vector; ... void MyClass::DoThis(std::vector<std::string> Vector) { const char *arrString;
9
3779
by: Fei Liu | last post by:
In Accellerated C++, the author recommends that in a header file one should not declare using std::string, using std::vector etc instead one should directly specify the namespace specifier in code. for example, this is bad practice: header.h #include <string> using std::string;
5
8830
by: Jae | last post by:
Real(const string &fileName) { FILE * myInputFile = fopen(fileName, "rt"); ..... fclose(myInputFile);
2
10910
by: pookiebearbottom | last post by:
Just looking for opinion on which of the 3 methods below people use in their code when they convert a 'const char *' to a 'const std::string &' came across #3 in someone's code and I had to think for a sec. At first I read it as converting a 'const char *' to a 'std::string *' void f(const std::string &s) { std::cout << s.size() << "\n";
2
3614
by: HerbD | last post by:
I have a loooong debugging session behind me! I finally found the reason for the problem and now would like to know, if it is a bug in my code or not standardconformant behavour of the compiler(s) or not a bug at all and just normal behavior: This simple sample program illustrates the problem. Please use separate header (.h) and code (.cpp) files, because it plays a role in the problem... /************************************** * Module: ...
9
5730
by: Christopher | last post by:
Code compiles, but the string evaluates to NULL in debugger. Using gcc 3.1.1. Did I not initialize the string properly or is this a compiler bug? // some.h #include <string> namespace ns {
0
8750
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9244
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, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8961
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
7853
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 launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
6585
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
4679
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3114
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
2
2439
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2058
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 effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.