This question already has answers here:
Why is "using namespace X;" not allowed at class/struct level?
(6 answers)
Closed 3 years ago.
I once heard/read (reference has slipped my mind; unable to cite it) that the "using namespace" clause is valid in any scope, but it appears to not be valid in a class scope:
// main.cpp
#include <iostream>
namespace foo
{
void func() { std::cout << __FUNCTION__ << std::endl; }
};
class Foo
{
using namespace foo;
public:
Foo() { func(); }
};
int main( int argc, char* argv[] )
{
Foo f;
}
.
$ g++ --version
g++ (GCC) 8.3.1 20190223 (Red Hat 8.3.1-2)
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
.
$ g++ -g ./main.cpp
./main.cpp:12:7: error: expected nested-name-specifier before 'namespace'
using namespace foo;
^~~~~~~~~
./main.cpp: In constructor 'Foo::Foo()':
./main.cpp:15:13: error: 'func' was not declared in this scope
Foo() { func(); }
^~~~
./main.cpp:15:13: note: suggested alternative:
./main.cpp:7:8: note: 'foo::func'
void func() { std::cout << __FUNCTION__ << std::endl; }
^~~~
$
$ g++ --std=c++11 -g ./main.cpp
./main.cpp:12:7: error: expected nested-name-specifier before 'namespace'
using namespace foo;
^~~~~~~~~
./main.cpp: In constructor 'Foo::Foo()':
./main.cpp:15:13: error: 'func' was not declared in this scope
Foo() { func(); }
^~~~
./main.cpp:15:13: note: suggested alternative:
./main.cpp:7:8: note: 'foo::func'
void func() { std::cout << __FUNCTION__ << std::endl; }
^~~~
The following variation of class Foo results in the same compiler error:
class Foo
{
using namespace ::foo;
public:
Foo()
{
func();
}
};
The following variations of class Foo result in no compiler errors or warning:
class Foo
{
public:
Foo()
{
using namespace foo;
func();
}
};
.
class Foo
{
public:
Foo()
{
foo::func();
}
};
My (incorrect?) understanding of the compiler error, based on reading posts such as this and this, is that error essentially requires full scoping of the used namespace, i.e. what I attempted in the first variation to class Foo, above.
Please note: in addition to explicit use of the --std=c++11 compiler flag, the compiler version used is well above the minimum necessary to not encounter this error (without explicit use of the --std=c++11 compiler flag), according to the noted Stack Overflow Q&A.
What does this compiler error mean (if different than my above-stated understanding) in this context? (My use appears different than that in the two noted Stack Overflow Q&A).
In general: in what scopes is the "using namespace" directive valid?
From cppreference.com:
Using-directives are allowed only in namespace scope and in block scope.
So you can use them within a namespace (including the global namespace) or within a code block. A class declaration is neither of those.
Related
A simple program as below, no c++11 syntax at all (e.cpp)
#include<iostream>
using namespace std;
namespace m{
class my{
public:
enum A{
u=1,
v=2,
w=3
};
static A f(A a){
return (A)(a + A::u);
}
};
int main(){
using namespace m;
my::A r=my::f(my::u);
return 0;
}
Using g++4.1.2 to compile it:
e.cpp:17:2: warning: no newline at end of file
e.cpp: In static member function ‘static m::my::A m::my::f(m::my::A)’:
e.cpp:11: error: expected primary-expression before ‘)’ token
e.cpp:11: error: ‘A’ is not a class or namespace
Using g++4.9.2 with -std=c++98
g++ e.cpp -std=c++98
e.cpp: In static member function ‘static m::my::A m::my::f(m::my::A)’:
e.cpp:11:36: error: ‘A’ is not a class or namespace
static A f(A a){return (A)(a + A::u);}
^
But using -std=c++11 is ok:
g++ e.cpp -std=c++11
To make it compile using c++98, I change it to avoid "A::" to be:
static A f(A a){return (A)(a + u);}
So seems that under c++98, the embeded enum class is not recognized inside a class, while in c++11 it works. Is this a difference in enum resolution, or some previous syntax bug in c++98 standard?
Enum values are not scoped by the enum type (either in C++98 or C++11). In the following example:
namespace N {
enum E { X };
}
X is directly in the scope of namespace N. Its fully qualified identifier would be ::N::X.
This behaviour was changed by C++11, where following the same definition, the identifier of X can also be referred using ::N::E::X:
[dcl.enum/11]
An enumerator declared in class scope can be referred to using the class member access
operators (::, . (dot) and -> (arrow)), see 5.2.5. [ Example:
struct X {
enum direction { left=’l’, right=’r’ };
int f(int i) { return i==left ? 0 : i==right ? 1 : 2; }
};
void g(X* p) {
direction d; // error: direction not in scope
int i;
i = p->f(left); // error: left not in scope
i = p->f(X::right); // OK
i = p->f(p->left); // OK
// ...
}
—end example ]
The enumeration name could not be used to qualify an enumerator prior to C++11. So there is no bug in C++98 mode, the code is just ill-formed.
You are correct in deducing the rules have changed.
The C++ FAQ lists the changes made to enumerations in C++11, and cites the proposals that drove those changes.
Here is the code:
struct foo {
template<typename T = void>
friend foo f() { return {}; }
};
int main() {
auto x = f(); // clang++ can't find it, g++ can.
}
clang++ 3.4 gives:
fni2.cpp:8:12: error: use of undeclared identifier 'f'
auto x = f(); // clang++ can't find it, g++ can.
^
1 error generated.
g++ 4.9.0 compiles it, but I don't think it should have. This is a related question, but there was no definitive answer. Section 15.4.2/2,4 discuss this, but neither of them say anything to suggest that friend function templates defined in-class should have different visibility from non-template friend functions defined in-class.
This is of academic interest to me only, though it did arise from a question by someone else who may have had an actual use case.
It looks like a g++ bug to me.
Yes, this is an error. I'm surprised it's finding the function. Apparently GCC fails entirely to hide function templates.
This C++03 example also compiles, so it could be a regression:
struct foo {
template<typename T >
friend void f( T ) { }
};
int main() {
f( 3 ); // clang++ can't find it, g++ can.
}
I'm wondering if the following code should be considered valid c++, gcc and clang both choke on it while Microsoft and the embedded compiler (green hills) our project uses seem to parse this without problems. This line of code gives gcc and clang trouble:
foo().Bar<int>();
It appears gcc thinks the < is a less than operator instead of specifying a template argument. If Bar is changed to not be a template function gcc accepts it.
class Test1
{
public:
template<typename U>
static void Bar() {}
};
template<typename T>
class Test2
{
public:
Test2()
{
foo().Bar<int>();
}
Test1 foo() { return t; }
Test1 t;
};
int main()
{
Test2<int> t;
}
From my research calling a static member function on an object instance is valid c++. So what are you thoughts? Here is gcc's error:
Error.cpp: In constructor ‘Test2<T>::Test2()’:
Error.cpp:14:17: error: expected primary-expression before ‘int’
foo().Bar<int>();
^
Error.cpp:14:17: error: expected ‘;’ before ‘int’
The correct syntax is:
foo().template Bar<int>();
(Adding to #Dieter answer)
Otherwise you have to use a temporary:
Test1 tt = foo();
tt.Bar<int>();
(in this case you could have simply used t instead of tt, but that was not the point, of course).
To store the functions of a class in an array the following link http://sourcemaking.com/design_patterns/state/cpp/1 contains the code like below (Machine is the class name).
void(Machine:: *ptrs[])() =
{
Machine::off, Machine::on
};
The example in that link does not compile with the g++ compiler throwing error as below
$ g++ state.cpp
state.cpp: In function ‘int main()’:
state.cpp:89:18: error: invalid use of non-static member function ‘void Machine::off()’
state.cpp:89:32: error: invalid use of non-static member function ‘void Machine::on()’
state.cpp:97:15: error: expected unqualified-id before ‘*’ token
I am using g++ version 4.5.2
$ g++ --version
g++ (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Can an array be defined like this, i am not able to find an array defination like this any where else. If the example is correct why does not it compile.
If you define a typedef for your member functions you will simplify your code greatly.
class Machine
{
public:
void on(){}
void off(){}
};
int main()
{
typedef void (Machine::*MachineFunctionPtr)();
MachineFunctionPtr temp[] = { &Machine::off , &Machine::on };
//To invoke a function use this syntax
Machine mymachine;
((mymachine).*(temp[1]))();
The being said your error is due to missing "&" before the function name.
If you don't want to use typedef the correct way is something like
void(Machine:: *ptrs[])() =
{
&Machine::off, &Machine::on
};
Machine fsm;
int num;
while (1)
{
cout << "Enter 0/1: ";
cin >> num;
((fsm).*(ptrs[num]))();
}
To be able to add your member-function-pointers to your array you'll need to prepend their identifiers with the address-of operator &.
Example:
struct Obj {
void func_1 () {}
void func_2 () {}
};
int
main (int argc, char *argv[])
{
void (Obj::* pointers[]) () = {
&Obj::func_1, &Obj::func_2
};
}
This is the more c++ way to do it :
#include <vector>
#include <iostream>
struct A {
typedef void (A::*memfpt)();
A() : arr( { &A::foo, &A::bar } )
{}
void foo()
{
std::cout<<"foo"<<std::endl;
}
void bar()
{
std::cout<<"bar"<<std::endl;
}
std::vector< memfpt > arr;
};
int main() {
A a;
for ( auto &it : a.arr )
{
(a.*it)();
}
}
Instead of raw array, I used std::vector, and instead of that unspeakable abomination, I used the typedef.
Your specific example doesn't compile because :
line 97 : (fsm. *ptrs[num])(); should be (fsm.*ptrs[num])(); - you need to remove that space, because calling a pointer to member function should be done using .* or ->*
line 89 : Machine::off, Machine::on should be &Machine::off, &Machine::on because that is how you get pointer to member function.
I have the following code (stripped down version from actual project to reproduce
the issue) that results in a compiler error on RHEL5 (g++ version 4.1.2):
----------- driver (test.cpp)--------------
#include <iostream>
#include <classa.hpp>
#include <func.hpp>
namespace globals {
static int kth(const A& a) {
return kth(a.ival());
}
}
using namespace globals;
int main() {
A a;
std::cout << func(a) << std::endl;
return 0;
}
----------class A (classa.hpp)------------
class A {
public:
A():val(0){}
const int ival() const {return val;}
private:
int val;
};
------- namespace globals (func.hpp) ------
namespace globals {
int kth(const int& c) {
return c;
}
template <class T>
int func(const T& key) {
return kth(key);
}
}
--------------------------------------------
Compiling it using g++ 4.1.2 gives me the following error:
func.hpp: In function ‘int globals::func(const T&) [with T = A]’:
test.cpp:15: instantiated from here
func.hpp:8: error: invalid initialization of reference of type ‘const int&’ from
expression of type ‘const A’
func.hpp:2: error: in passing argument 1 of ‘int globals::kth(const int&)’
Same code compiles and runs perfectly fine on RHEL4 (g++ version 3.4.6)! Any explanations/ideas/suggestions on how to resolve this error(?) on RHEL5 will
be much appreciated!
Edit:
Thanks Sergey. That is the obvious solution that I am aware of already. But I forgot to add that the restriction is that func.hpp cannot be edited (for e.g., its 3rd party write-protected). Any workarounds?
Here's what happens. When the function func() is defined, the compiler doesn't know about the function kth(const A&) yet because it is defined later in the code. So when it encounters a reference to kth() inside func(), it assumes that it is a reference to kth(const int&). Now when func() is actually instantiated, it fails to compile it because T is A, not int. I am not sure why it works in another version of the compiler, but I think it is because it actually starts resolving references when a template function is instantiated, not when it is declared. But this looks like a bug in the older version because with such behavior a function definition changes depending on where it is instantiated from, which is very confusing.
The only way to fix your code that it works with any compiler would be to put the definition of kth(const A&) between kth(const int&) and func() or a forward declaration of kth(const A&) somewhere above func().
Update
With the restriction of not editing func.hpp the best workaround I can think of is to create a custom header file with something like this:
#include <classa.hpp>
namespace globals {
static int kth(const A& a); // defined later, but used by func.hpp
}
#include <func.hpp>
I also don't see why kth(const A&) is defined as static, but used by a global header. I'd rather put it into the classa.cpp and its declaration into the classa.hpp. But this may be some design feature or artifact I am not aware of.