3

Simple bit of code. It's obviously incomplete as of this point, but it should compile. I'm converting this to Linux from Visual Studio. When I compile with g++ test.cpp I get this error:

In file included from test.cpp:2:0:
String.h: In constructor String::String(char*):
String.h:24:2: error: strcpy is not a member of std std::strcpy(pointer_Object, s);

#ifndef _STRING_H
#define _STRING_H

#include <cstring>
#include "ArrayClass.h"
#include "Exception.h"

class String : virtual public ArrayClass<char>
{

public:
    String();
    String(char* s);

};

String::String() : ArrayClass<char>(1,'\0') {}

String::String(char* s) : ArrayClass<char>(std::strlen(s)+1)
{
    std::strcpy(pointer_Object, s);
}

#endif

It seems like I've been over it backwards and forwards. Any Ideas?

Compiling with these:

  • libgcc-4.9.2-6.fc21.i686

  • gcc-4.9.2-6.fc21.x86_64

  • gcc-c++-4.9.2-6.fc21.x86_64

  • libgcc-4.9.2-6.fc21.x86_64

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100

3 Answers3

6

It appears that you've hacked string.h's include guard.

#ifndef _STRING_H
#define _STRING_H

It's illegal to do this, and unclear why you did. #include <cstring> is all that is necessary.

The likely result is that <string.h> gets ignored, which will cause things to be missing from the global namespace which <cstring> expects.

EDIT: Ah, now I see. Your header is also named "string.h".

Names starting with an underscore followed by a capital letter are reserved to the implementation: the compiler and the standard library. They can be internal-use operators, or internal variables (such as include guards for system headers). Try this instead:

#ifndef INCLUDED_SEANS_STRING_H
#define INCLUDED_SEANS_STRING_H

Since macros are all lumped into only one namespace, it's up to you to use macro names that don't collide with anything else. Some folks go so far as to put UUIDs in header guards; I just mention the name of the library.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • Defining headers that way was how I was taught: Data Structures Featuring C++ Sridhar Radhakrishnan, Lee Wise, Chandra Sekharan. Why is it illegal? – Sean O'Bleness Jul 29 '15 at 04:37
  • @SeanO'Bleness The identifier `_STRING_H` collided with something inside the compiler. The answer is updated with the info, try reloading the page. – Potatoswatter Jul 29 '15 at 04:38
  • 4
    @SeanO'Bleness By the way, there are a lot of poor-quality C++ books in circulation. The Amazon reviews of that book suggest it is one of them, and if it contains header guards starting with underscores, the authors are probably not competent. Try something from the [SO curated list](http://stackoverflow.com/q/388242/153285). – Potatoswatter Jul 29 '15 at 04:43
  • Good advice. I was in Dr Radhakrishnans class, so it was the book we used. The code compiles under MSVS. Why is it bad practice to use underscores? is it because they are reserved to avoid collisions? – Sean O'Bleness Jul 29 '15 at 04:51
  • 1
    @SeanO'Bleness Identifiers beginning with underscore-capital are reserved. You're forbidden to use them, except when they are specifically documented by the language or the C++ compiler. Header guards like this are a common mistake, ironically caused by using the standard library as an example. Of course, if you copy-paste from your system headers, you will get a collision. But many programmers, even experienced ones, tend to unquestioningly follow patterns they see. – Potatoswatter Jul 29 '15 at 04:58
  • @SeanO'Bleness The standard library is a specific exception to the normal rules forbidding underscores, As it is part of the implementation itself if it allowed and indeed encouraged to use underscore prefixed to avoid collision with user code, that is the main purpose of the underscore starting identifiers, it separates user libraries from the standard libraries which are part of the implementation with a simple, well defined rule. – Vality Jul 29 '15 at 08:49
4

It isn't legal in C++ to start any identifier including a macro with an _ followed by a capital letter. Therefore:

#ifndef _STRING_H
#define _STRING_H

should be changed to something else that doesn't break this rule.

The working from the standard:

7.1.3 Reserved identifiers

Each header declares or defines all identifiers listed in its associated subclause, and optionally declares or defines identifiers listed in its associated future library directions subclause and identifiers which are always reserved either for any use or for use as file scope identifiers.

  • All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use.
  • All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

To go into a little more detail, what is probably happening is that your implementation of <cstring> is using _STRING_H as its own include guard, and therefore when you include it it is being masked out by the repeated guard #ifdef. So as I said, the best solution is just to use a standards compliant macro name that doesn't begin with an _

Community
  • 1
  • 1
Vality
  • 6,577
  • 3
  • 27
  • 48
-4

It's not in std namespace, just use strcpy

  • I have looked at the example in [http://www.cplusplus.com/reference/cstring/strcpy/](http://www.cplusplus.com/reference/cstring/strcpy/), where it appears with no namespace. Seems like (at least, for Visual Studio), it's defined as **std** when including `` and not pard of **std** when including `` – Michael Gopshtein Jul 29 '15 at 06:57
  • that is correct, string.h is the C header, while cstring is the c++ header, C does not support namespacing so declares it globally, but using cstring will put it into std:: Otherwise the teo headers are very similar – Vality Jul 29 '15 at 08:46