This is a follow-up question from: constructing string from NULL?
The following:
void test(const std::string& s);
int main(){
test(NULL);
}
Fails when run, but is legal c++.
In order to try to catch some of those cases, as an alternative ive considering if std::string can be replaced in the following way:
#include <string>
namespace {
namespace std {
struct string : public ::std::string { //so far everything is good
};
}
}
int main ()
{
std::string hello;//failure: ambiguous symbol
return 0;
}
Gives the following error:
<source>(17): error C2872: 'std': ambiguous symbol
C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'
<source>(7): note: or '`anonymous-namespace'::std'
<source>(17): error C2872: 'std': ambiguous symbol
C:/data/msvc/14.22.27905/include\string(19): note: could be 'std'
<source>(7): note: or '`anonymous-namespace'::std'
Compiler returned: 2
I guess it is not possible to make it resolve without writing a more (fully) qualified name ? but is it possible to write std::string in the global namespace and have it resolve to something else while ::std::string is a valid type.
Background: after some failed attempts with cppcheck and cpp core check im trying to find all cases of std::string str = 0 or NULL or nullptr - since those will fail at runtime. And I thought this might be a way forward.
I ended up modifying the basic_string template ala. basic_string(int) = delete;
basic_string(::std::nullptr_t) = delete; - this won't catch all cases but does indeed seem to catch the direct cases at least
Resolve std::string to something else than ::std::string - is it possible?
[...]
...as an alternative ive considering if std::string can be replaced in the following way...
As far as I know, it is not possible outside of your anonymous namespace scope because you have no way to resolve the ambiguity (not to my knowledge).
As you can see below, since you are inside the scope of the anonymous namespace, it will be fine:
#include <string>
namespace
{
namespace std
{
struct string : public ::std::string
{
};
}
std::string hello; // Fine
}
int main()
{
std::string hello2; // Cannot be something else that ambiguous
return 0;
}
But even worse, the problem is not about std::string itself but about the std namespace.
Indeed, outside of the scope of your anonymous namespace, every call of std becomes ambiguous too.This is the error pointed by the compiler. There are two std namespaces accessible as is from the global scope.
So the following example becomes broken:
#include <string>
#include <vector>
namespace
{
namespace std
{
struct string : public ::std::string
{
};
}
std::string hello; // Fine
}
int main()
{
std::vector<int> a; // FAIL: reference to 'std' is ambiguous
return 0;
}
To fix this ambiguity over accessing the original std namespace, you'll need to write it as follows:
::std::vector<int> a; // Fully qualified name: Only way to refer to the `::std` namespace
As you can see, it still does not solve the issue and even worse, it adds a huge inconvenience.
Therefore the morality is:
Do not hide an already existing type but create a distinct one instead.
In the same way, do not hide a namespace (by defining the same namespace into an anonymous one --> evil).
(I'm open to any improvement proposal of this answer)
Could you use this kind of solution : Rather than working on std::string, you work on the function that will cause the problem
#include <string>
void test(const std::string& s){
}
// add a new function which use a pointer :
void test (const char* _Nonnull s) {
test(std::string(s));
}
int main()
{
test(NULL);
return 0;
}
Then clang will generate a warning :
1 warning generated.
ASM generation compiler returned: 0
<source>:13:14: warning: null passed to a callee that requires a non-null argument [-Wnonnull]
test(NULL);
see https://godbolt.org/z/PujFor
Related
A project I'm working on requires multiple targets to be compiled for. Per target the underlying implementation may vary as the device requires hardware to be configured differently.
In order to force target implementations to follow a interface/design contract system was designed. If a target does not implement said interface accordingly, an error will be thrown upon usage.
The following code is tested using gcc, arm-none-eabi-gcc and clang
namespace A {
namespace C {
void foo() {}
}
}
namespace B {
using namespace A::C;
void foo() {}
}
using namespace A;
namespace C {
}
int main() {
B::foo(); // ok
C::foo(); // won't compile
return 0;
}
Now there are multiple questions that arise when reasoning why this code would compile or not:
Why does the compiler not report unresolved ambiguity between A::foo(bool) and B::set(bool)?
Why does C::foo() not compile, since my theory is that the same naming structure is achieved but on a different manner:
Why does the compiler not report unresolved ambiguity between target::set(bool) and interface_contracts::set(bool)?
In the first code snippet, name hwstl::target::pin::set hides name hwstl::interface_contracts::pin::set.
For the call hwstl::device::pin::set(true);, name lookup stops upon finding hwstl::target::pin::set. Only one candidate function, no ambiguity.
For the call hwstl::unsatisfied_device::pin::set(true);, there is only one function called set which can be found anyway.
10.3.4.1 A using-directive does not add any members to the declarative region in which it appears.
Why does the following code not compile?
In the second code snippet, you call set by qualified id: hwstl::unsatisfied_device::pin::set, compiler will only try to find name inside namespace hwstl::unsatisfied_device::pin. Thus it failed in finding the name introduced by the using directive using namespace interface_contracts; outside it.
Here is a simplified version of your code:
namespace A {
void foo() {}
}
namespace B {
using namespace A;
void foo() {}
}
using namespace A;
namespace C {
}
int main() {
B::foo(); // ok
C::foo(); // won't compile
return 0;
}
See code below
#include <iostream>
#include <string>
namespace stringhelper
{
std::string to_string(int n) { return "0"; } // ignore wrong implementation. simplified for example purpose
}
using stringhelper::to_string;
class TestClass
{
public:
std::string to_string() const { return "TestClass:" + to_string(m_value); }
private:
int m_value;
};
int main()
{
TestClass tc;
std::cout << tc.to_string();
}
If TestClass does not implement function to_string(), within TestClass, it is able to resolve to_string(m_value) to stringhelper::to_string(int). However, the moment TestClass implements function to_string(), the compiler is unable to resolve to_string(int) to stringhelper::to_string.
Rather, it insists/resolves the function to TestClass::to_string and gave an error that the function TestClass::to_string does not take in 1 arguments.
Why is this so?
Environment:
Visual Studio 2008 Professional Edition 9.0.21022.8 RTM
Configuration: Win32
Windows 8
This behavior is not limited to Visual Studio 2008. If tested in modern Clang implementations you will see the same behaviour. As you may know, functions in derived classes which don't override functions in base classes but which have the same name will hide other functions of the same name in the base class.
The "problem" here is that you, by using the using statement introduces a function named to_string into a scope that is essentially a victim of the exact same thing as what happens in the above example, when looking at it from inside your class.
If the standard had you call member functions with this->foo() this would probably not have been an issue. But since function calls within a class are presumed to be part of the class and only if not found looked for in other scopes this becomes an issue.
Since you have an implementation in your class, that has priority and will be used. Since you want a version that takes an int as an argument, an overloaded version of your member function will be looked for and since it does not exist you get the error you see.
This is part of why using namespace can often introduce errors that might be unintuitive to understand. If you want to make sure you use the stringhelper::to_string implementation while you are in a class with a function that has the same name you have to be explicit.
This would work fine for instance, even if you keep your using statement.
#include <iostream>
#include <string>
namespace stringhelper
{
std::string to_string(int n) { return "0"; } // ignore wrong implementation. simplified for example purpose
}
using stringhelper::to_string;
class TestClass
{
public:
std::string to_string() const { return "TestClass:" + stringhelper::to_string(m_value); }
private:
int m_value;
};
int main()
{
TestClass tc;
std::cout << tc.to_string();
}
#include<iostream>
#include<stdlib.h>
#include<string.h>
using namespace std;
class div
{
int x,y;
public:
class dividebyzero
{
};
class noerror1
{
};
div(){};
div(int a,int b)
{
x=a;
y=b;
}
void error1()
{
if(y==0)
throw dividebyzero();
else
throw noerror1();
}
int divide()
{
return (x/y);
}
};
class naming
{
char name[32];
public:
class nullexception
{
};
class noerror2
{
};
naming(char a[32])
{
strcpy(name,a);
}
void error2()
{
if(strcmp(name,"")==0)
throw nullexception();
else
throw noerror2();
}
void print()
{
cout<<"Name-----"<<name<<endl;
}
};
int main()
{
div d(12,0);
try
{
d.error1();
}
catch(div::dividebyzero)
{
cout<<"\nDivision by Zero-------Not Possible\n";
}
catch(div::noerror1)
{
cout<<"\nResult="<<d.divide()<<endl;
}
naming s("Pankaj");
try
{
s.error2();
}
catch(naming::nullexception)
{
cout<<"\nNull Value in name\n";
}
catch(naming::noerror2)
{
s.print();
}
return 0;
}
On compiling this program I am getting following error
pllab55.cpp: In function ‘int main()’:
pllab55.cpp:61:6: error: expected ‘;’ before ‘d’
pllab55.cpp:64:3: error: ‘d’ was not declared in this scope
pllab55.cpp:72:22: error: ‘d’ was not declared in this scope
pllab55.cpp:74:20: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
Before declaring the class naming everything was running fine.It is after declaration of naming these error started to occur. I am new to C++. Please explain me in details. Thanks in advance.
There is already an std::div in the standard namespace and since you use a using namespace directive instead of declaration it imports all the symbols in std namespace to your current scope. So perhaps renaming the div class shall do the trick for you.
I tried renaming it and it does work indeed.
So either rename your class or wrap it in your own namespace so it does not conflict with std::div
Your class div shares the same name as std::div. When you do #using namespace std, the result is that each class in the std namespace is imported into your current scope, meaning that std::div is now essentially called div. If you see, that means you now have two classes called div in the same scope, your own and the std class.
By the way, you should avoid the using namespace syntax and rather use the full qualifier of the class (e.g. std::cout).
Your div class is conflicting with std::div so either rename yours or put put your div class in a different namespace.
namespace me {
struct div{};
}
me::div d;
I gave (a slight variant of) your code a try in gcc and I got the following error:
/usr/include/stdlib.h:780: error: too few arguments to function 'div_t div(int, int)'
You're trying to override a name from a standard library and experience the conflict of a class and a function having the same name, I'm afraid.
as a general rule of thumb, if you encounter such issues, try to reduce your code as much as possible. For instance, I reduced it down to
#include<stdlib.h>
class div {
public:
div (int a, int b) { }
};
int
main () {
div d (12, 0);
return 0;
}
which still shows your error (at least the first one - the others are followup errors).
This lets you also reduce possible assumptions about the reason for the error - as you see, your new class "naming" does not have to do anything with the error you see.
When I now additionally remove the include, the error does not show up anymore, which lets me suspect some naming clash with some symbol from stdlib.h. After renaming the class "div" to something else (like "CDiv"), it works.
Is there any difference between wrapping both header and cpp file contents in a namespace or wrapping just the header contents and then doing using namespace in the cpp file?
By difference I mean any sort performance penalty or slightly different semantics that can cause problems or anything I need to be aware of.
Example:
// header
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
// cpp
namespace X
{
void Foo::TheFunc()
{
return;
}
}
VS
// header
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
// cpp
using namespace X;
{
void Foo::TheFunc()
{
return;
}
}
If there is no difference what is the preferred form and why?
The difference in "namespace X" to "using namespace X" is in the first one any new declarations will be under the name space while in the second one it won't.
In your example there are no new declaration - so no difference hence no preferred way.
Namespace is just a way to mangle function signature so that they will not conflict. Some prefer the first way and other prefer the second version. Both versions do not have any effect on compile time performance. Note that namespaces are just a compile time entity.
The only problem that arises with using namespace is when we have same nested namespace names (i.e) X::X::Foo. Doing that creates more confusion with or without using keyword.
There's no performance penalties, since the resulting could would be the same, but putting your Foo into namespace implicitly introduces ambiguity in case you have Foos in different namespaces. You can get your code fubar, indeed. I'd recommend avoiding using using for this purpose.
And you have a stray { after using namespace ;-)
If you're attempting to use variables from one to the other, then I'd recommend externalizing them, then initializing them in the source file like so:
// [.hh]
namespace example
{
extern int a, b, c;
}
// [.cc]
// Include your header, then init the vars:
namespace example
{
int a, b, c;
}
// Then in the function below, you can init them as what you want:
void reference
{
example::a = 0;
}
If the second one compiles as well, there should be no differences. Namespaces are processed in compile-time and should not affect the runtime actions.
But for design issues, second is horrible. Even if it compiles (not sure), it makes no sense at all.
The Foo::TheFunc() is not in the correct namespacein the VS-case. Use 'void X::Foo::TheFunc() {}' to implement the function in the correct namespace (X).
In case if you do wrap only the .h content you have to write using namespace ... in cpp file otherwise you every time working on the valid namespace. Normally you wrap both .cpp and .h files otherwise you are in risk to use objects from another namespace which may generate a lot of problems.
I think right thing to do here is to use namespace for scoping.
namespace catagory
{
enum status
{
none,
active,
paused
}
};
void func()
{
catagory::status status;
status = category::active;
}
Or you can do the following:
// asdf.h
namespace X
{
class Foo
{
public:
void TheFunc();
};
}
Then
// asdf.cpp
#include "asdf.h"
void X::Foo::TheFunc()
{
return;
}
Sorry for this question but I am stuck.
I have folowing syntax:
class xx
{
..some simple fields like: int t; // )))
public: class anotherClass;
xx();
MyObj* obj();
string* name(); //error C2143: syntax error : missing ';' before '*'
}
i have write # include <string>
What does compiler wants from me?!
It wants you to tell him which string. You want the standard one:
class xx
{
public:
std::string* name();
};
Now, I'm not sure why you would be returning a pointer to a string. That's a segmentation fault waiting to happen, if you ask me. Two more viable options that seem reasonable to me:
class xx
{
std::string _name;
public:
const std::string& name() const
{
return _name; // WARNING: only valid as long as
// this instance of xx is valid
}
};
or
class xx
{
public:
std::string name() const { return "hello world"; }
};
You need to either fully qualify string or bring it into the current namespace:
std::string* name();
or
using std::string;
In a header, it's generally considered bad practice to pollute the global namespace, so the first is preferred.
The compiler does not know what string is because string is residing in the namespace std, not in the global namespace. You need to change string to std::string.
In your cpp file you can use "using namespace std;" or "using std::string;" and then just write "string". But you should never use using-namespace-declarations in header files.
BTW, as the others say returning a string* is unusal, normally you would return a string.