Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::strcpy not declared in this scope DESPITE #include <cstring>

Tags:

c++

gcc

c++11

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

like image 942
Sean O'Bleness Avatar asked Nov 27 '25 10:11

Sean O'Bleness


2 Answers

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.

like image 171
Potatoswatter Avatar answered Nov 30 '25 00:11

Potatoswatter


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 _

like image 27
Vality Avatar answered Nov 30 '25 00:11

Vality



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!