What is going on here? - c++

This doesn't compile,
#include <boost/intrusive_ptr.hpp>
class X
{
public:
void intrusive_ptr_add_ref(X* blah)
{
}
void intrusive_ptr_release(X * blah)
{
}
};
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
But this does :
#include <boost/intrusive_ptr.hpp>
class X
{
public:
friend void intrusive_ptr_add_ref(X* blah)
{
}
friend void intrusive_ptr_release(X * blah)
{
}
};
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
and this :
#include <boost/intrusive_ptr.hpp>
class X
{
public:
};
void intrusive_ptr_add_ref(X* blah)
{
}
void intrusive_ptr_release(X * blah)
{
}
int main()
{
boost::intrusive_ptr<X> ex(new X);
}
I suppose it has something to do with SFINAE (which I haven't as of yet bothered to understand) ? Does the friend qualifier put the defined function as a free function in the enclosed namespace ?
edit
Whoever removed their post, member functions non-friend as add_ref and release (these specific member functions are not mentioned in the documention...) did solve the problem. What happens with the nested definition with the friend qualifier ?

From the documentation of boost::intrusive_ptr:
Every new intrusive_ptr instance increments the reference count by using an unqualified call to the function intrusive_ptr_add_ref, passing it the pointer as an argument. Similarly, when an intrusive_ptr is destroyed, it calls intrusive_ptr_release; this function is responsible for destroying the object when its reference count drops to zero. The user is expected to provide suitable definitions of these two functions. On compilers that support argument-dependent lookup, intrusive_ptr_add_ref and intrusive_ptr_release should be defined in the namespace that corresponds to their parameter; otherwise, the definitions need to go in namespace boost.
This means that intrusive_ptr_add_ref and intrusive_ptr_release should not be member functions, but free functions (friend functions behave as such). Furthermore they are called without qualification, so they should be in the global namespace or somewhere found by ADL.
Edit: To your question about nested definitions with friend qualifier:
friend functions are defined as non memberfunctions, so friend void intrusive_ptr_add_ref(X* blah) will be called as intrusive_ptr_add_ref(my_x_ptr) instead of as my_x_ptr->intrusive_ptr_add_ref().

Related

Namespace's class's friend that is not declared and defined in the namespace

Is it right to do so:
void f();
namespace ns
{
class C
{
int m;
friend void ::f();
};
}
void f()
{
ns::C c;
c.m = 2;
}
?
The code is compiled successfully in VS. But I can't find anything about qualifying a namespace for a friend declaration in the standard. Is it even legal? Can someone provide the link or the quote from the standard?
Yes it's legal.
A namespace is little more than a way of adding another layer of descrimination for functions, classes, &c..
Any function can be marked as a friend inside a class, even if that class is in a different namespace to the function. The function could be in a namespace too.
There's no specific section in the standard on this, but it's a corollary of the standard. This reference is a starting point: https://en.cppreference.com/w/cpp/language/namespace

How can I access a protected constructor from a friend function?

I created a class and I want to force anyone who's trying to construct an object, to use unique_ptr. To do that I thought of declaring the constructor protected and use a friend function that returns a unique_ptr. So here's an example of what I want to do:
template <typename T>
class A
{
public:
friend std::unique_ptr<A<T>> CreateA<T>(int myarg);
protected:
A(int myarg) {}
};
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
// Since I declared CreateA as a friend I thought I
// would be able to do that
return std::make_unique<A<T>>(myarg);
}
I did some reading on friend functions and I understood that a friend function provides access to private/protected members of an object of a class.
Is there anyway I can make my example work?
Even without friend functions, my goal is to make the CreateA the only way for someone to create an object.
EDIT
I change the code a bit. I didn't mention that my class takes one template parameter. That makes things more complex apparently.
You can do it this way :-
#include <iostream>
#include <memory>
using namespace std;
class A
{
int arg;
public:
friend unique_ptr<A> CreateA(int myarg);
void showarg() { cout<<arg; }
protected:
A(int myarg): arg(myarg) {}
};
unique_ptr<A> CreateA (int myarg)
{
return std::unique_ptr<A>(new A(myarg));
}
int main()
{
int x=5;
unique_ptr<A> u = CreateA(x);
u->showarg();
return 0;
}
Output :-
5
If you don't want to use friend function you can make the function static & call it like this :-
unique_ptr<A> u = A::CreateA(x);
EDIT :-
In reply to your edit I rewrote the program & it goes like this :-
#include <iostream>
#include <memory>
using namespace std;
template <typename T>
class A
{
T arg;
public:
static std::unique_ptr<A> CreateA(T myarg)
{
return std::unique_ptr<A>( new A(myarg) );
}
void showarg()
{
cout<<arg;
}
protected:
A(T myarg): arg(myarg) {}
};
int main()
{
int x=5;
auto u = A<int>::CreateA(x);
u->showarg();
return 0;
}
Simple & easy !!! But remember you cannot instantiate the object of A. Good Luck !!!
The other answers suggest using a static template function, which I agree is the best solution, because it is simpler.
My answer explains why your friend approach didn't work and how to use the friend approach correctly.
There are two problems in your original code. One is that make_unique is not actually a friend of A, so the call make_unique<A<T>>(myarg); does not have access to A's protected constructor. To avoid this , you can use unique_ptr<A<T>>(new A(myarg)) instead. Theoretically it would be possible to declare make_unique a friend but I'm not even sure of the right syntax for that.
The other issue is the template friends problem. Inside a class template, friend <function-declaration> actually declares a non-template friend.
The C++ FAQ suggests two possible workarounds. One of them is to define the friend function inline. However, in that case the function can only be found by argument-dependent lookup. But since the function does not take A<T> (or A<T> &) as argument, it can never be found this way. So this option is not viable to your situation -- it's more suited to operator overloading.
So the only fix is to declare (and optionally define) the template function before the class definition:
#include <memory>
template<typename T>
class A;
template <typename T>
std::unique_ptr<A<T>> CreateA(int myarg)
{
return std::unique_ptr<A<T>>{new A<T>(myarg)};
}
template <typename T>
class A
{
friend std::unique_ptr<A<T>> CreateA <> (int myarg);
// refers to existing template ^^
protected:
A(int myarg) {}
};
int main()
{
auto x = CreateA<int>(5);
}
Note: It is possible to declare CreateA where I have defined it, and put the function definition later. However, the code I have posted works -- despite A not being defined when new A<T>(myarg) appears in the source -- because CreateA is not instantiated until it is called, at which point A will be defined.
Create a static function that instantiates the protected constructor.
#include<iostream>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include <memory>
using namespace std;
template< typename T >
class A
{
public:
static void CreateA(int myarg, std::unique_ptr<A<T>>& objA, T t) {
std::unique_ptr<A<T>> objB(new A(myarg, t));
objA = std::move(objB);
}
protected:
A(int myarg, T t) {
m_t = t;
}
private:
T m_t;
};
int main() {
int myArg = 0;
std::unique_ptr<A<int>> anotherObjA;
A<int>::CreateA(myArg, anotherObjA, myArg);
return 0;
}

How to make a function only seen by one function in c++?

How could I make a function only seen by the function that calls it?
define the function I want to hide as private function is not enough, as it could still be seen by other public functions in the class.
Now I use lambda expression to define anonymous function inside function. Is there any better solution?
Aside from using a lambda (which you've rejected), you could implement your function in its own compilation unit, and code the supporting function in an anonymous namespace within that compilation unit.
But that supporting function would be outside the class, so you'd have to pass it all the parameters it needed. That could become unwieldly though no worse than a long lambda capture list.
You can use a function object. For example(you can compile this, even in C++03):
#include <iostream> // only for output
class foo{
int bar(){return 0;} // Only foo can see this
public:
int operator()(){
return bar();
}
};
class baz{
public:
foo do_foo;
};
int main(){
baz a;
std::cout << a.do_foo() << std::endl;
}
the method bar is only visible by a foo.
P.S.: If you need foo to access members of baz, make it a friend.
A simmilar approach to cassiorenan would be to use static class functions and friends.
Something like this:
void Boss();
class Worker {
static void Test(){ return;}
friend void Boss();
};
void Boss(){
Worker::Test();
}
Though why would you want to do this, I don't know.
It is possible to define function inside a function without lambdas. Just define a struct that contains required function. This approach is not much better than using lambda, but at least this is straightforward and works with older compilers too.
int func() {
struct {
int hiddenFunc() {
return 1;
}
} h;
int a = h.hiddenFunc() + h.hiddenFunc();
return a;
}
As a slight variation from cassiorenan's solution, you could use a class containing one public static function (the visible function) and one static private function that could only be called from there. To avoid creation of objects of that class, it is enough to put a private constructor.
EDIT:
Per cassiorenan's comment, I can see that OP really needs methods and not functions. In that case, I would still use a dedicated class in a anonymous namespace to ensure it is not visible from elsewhere (even if my example is single file ...) friend to the class really used. So in below example, bar is the business class that would have a method with an externally hidden implementation (here relay_method), and foo is dedicated to the hidden method called with a pointer to the real object. In real world, the whole anonymous namespace and the implementation of the hidden method should be in the implementation file bar.cpp.
That way, the real implementation function priv_func can only be called from a bar object through bar::relay_method() and foo::bar_func(bar &).
#include <iostream>
class bar;
namespace {
class foo {
private:
static int priv_func(int i) {
return i * i;
}
foo() {}
public:
// only useful if true functions were needed
/* static int pub_func(int i, int j) {
return priv_func(i) + priv_func(j);
}*/
static void bar_func(bar& b);
};
}
class bar {
int x;
int x2;
public:
bar(int i): x(i) {}
void relay_method() {
foo::bar_func(*this);
}
friend class foo;
int getX2() const {
return x2;
}
};
void foo::bar_func(bar& b) {
b.x2 = foo::priv_func(b.x);
}
using namespace std;
int main() {
/* int i = foo::pub_func(3,4);
cout << i << endl;
// foo::priv_func(2); error access to private member of class foo
// foo f; */
bar b(2);
b.relay_method();
cout << b.getX2() << endl;
return 0;
}

ADL in case of equal-named member function

The situation is that some member function bar::Bar::frobnicate wants to utilize ADL to find a function from some unknown namespace, within a function that has an identical name. However, it only finds its own name.
Testcase
(Note that in reality, Bar is a Foo-agnostic template; this is just the reproducible, minimal testcase)
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
struct Bar {
void frobnicate() {
foo::Foo foo;
frobnicate(foo); // <-- error
}
};
}
int main () {
bar::Bar x;
x.frobnicate();
frobnicate(foo::Foo());
}
Results in:
test.cc: In member function ‘void bar::Bar::frobnicate()’:
test.cc:10:31: error: no matching function for call to ‘bar::Bar::frobnicate(foo::Foo&)’
test.cc:10:31: note: candidate is:
test.cc:8:18: note: void bar::Bar::frobnicate()
test.cc:8:18: note: candidate expects 0 arguments, 1 provided
Standard
I understand that this is correct compiler behaviour:
3.4.1 Unqualified name lookup [basic.lookup.unqual]
(...) name lookup ends as soon as a declaration is found for the name (...)
and only after unqualified lookup failed, argument dependent lookup comes into play:
3.4.2 Argument-dependent name lookup [basic.lookup.argdep]
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered
during the usual unqualified lookup (3.4.1) may be searched
Workaround
My current workaround is to introduce a special traits class that does not define the clashing name itself:
struct BarTraits {
void frobnicate_(foo::Foo const &b) {
frobnicate(b);
}
};
or this ligher version:
void frobnicate_(foo::Foo const &c) { frobnicate(c); }
Question
Are there better alternatives than introducing such traits classes?
Explicitly qualifying the call as foo::frobnicate(foo) is not an option here, because (as mentioned) the Bar class is a template upon Foo in reality and should not only work for types in the foo namespace.
As you found out yourself, adding a member function frobnicate to the class interface of Bar (or Bar<T> in the template case), will prevent ADL from finding foo::frobnicate.
The easiest -and in this case idiomatic- way to add frobnicate functionality to a class Bar (or to a class template Bar<T>) is to add a non-member function frobnicate(Bar) (or function template frobnicate(Bar<T>)) to the namespace bar
namespace foo {
struct Foo {};
void frobnicate(Foo const &) {}
}
namespace bar {
template<class T>
struct Bar {
T t;
};
template<class T>
void frobnicate(Bar<T> const& b)
{
frobnicate(b.t);
}
}
int main () {
bar::Bar<foo::Foo> x;
frobnicate(x);
frobnicate(foo::Foo());
}
If you insist on having a member function, you will have to rename it to something like do_frobnicate(). I would not use type traits tricks to get the same behavior as it is an indirect approach, and makes the class interfaces much harder to understand (remember Stroustrup's motto: "represent your ideas directly in code").
you can use this trick
namespace dummy { void your_func(may be some parameteres); }
struct bar {
void member() {
using dummy::your_func; // now your call will find that and ADL will kick in
I just do it with a proxy function
namespace utils
{
int lookup_adl(int arg)
{
return lookup(arg);// ADL search
}
struct Foo
{
int lookup(int arg) { return ::utils::lookup_adl(arg);}
};
}

Local Classes in C++

I am reading "Local Classes" concept in Object-oriented programming with C++ By Balagurusamy (http://highered.mcgraw-hill.com/sites/0070593620/information_center_view0/).
The last line says "Enclosing function cannot access the private members of a local class. However, we can achieve this by declaring the enclosing function as a friend."
Now I am wondering how the highlighted part can be done?
Here is the code I was trying but no luck,
#include<iostream>
using namespace std;
class abc;
int pqr(abc t)
{
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know the code looks erroneous, any help would be appreciable.
Your friend statement is fine.
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
friend int pqr();
};
return abc().x;
}
int main() {
cout << "Return " << pqr() << endl;
}
Edit:
IBM offers this explanation for the issue raised in the comments:
If you declare a friend in a local class, and the friend's name is unqualified, the compiler will look for the name only within the innermost enclosing nonclass scope. [...] You do not have to do so with classes.
void a();
void f() {
class A {
// error: friend declaration 'void a()' in local class without prior decl...
friend void a();
};
}
friend void a(): This statement does not consider function a() declared in namespace scope. Since function a() has not been declared in the scope of f(), the compiler would not allow this statement.
Source: IBM - Friend scope (C++ only)
So, you're out of luck. Balagurusamy's tip only works for MSVC and similar compilers. You could try handing off execution to a static method inside your local class as a work-around:
int pqr() {
class abc {
int x;
public:
abc() : x(4) { }
static int pqr() {
return abc().x;
}
};
return abc::pqr();
}
There seems to be a misunderstand about local classes.
Normally there are here to help you within the function... and should NOT escape the function's scope.
Therefore, it is not possible for a function to take as an argument its own local class, the class simply isn't visible from the outside.
Also note that a variety of compilers do not (unfortunately) support these local classes as template parameters (gcc 3.4 for example), which actually prevents their use as predicates in STL algorithms.
Example of use:
int pqr()
{
class foo
{
friend int pqr();
int x;
foo(): x() {}
};
return foo().x;
}
I must admit though that I don't use this much, given the restricted scope I usually use struct instead of class, which means that I don't have to worry about friending ;)
I have no solution for the friend thing yet (don't even know if it can be done), but read this and this to find out some more about local classes. This will tell you that you cannot use local classes outside the function they are defined in (as #In silico points out in his answer.)
EDIT It doesn't seem possible, as this article explains:
The name of a function first introduced in a friend declaration is in the scope of the first nonclass scope that contains the enclosing class.
In other words, local classes can only befriend a function if it was declared within their enclosing function.
The friend int pqr(abc); declaration is fine. It doesn't work because the abc type has not been defined before you used it as a parameter type in the pqr() function. Define it before the function:
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// Class defined outside the pqr() function.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
friend int pqr(abc);
};
// At this point, the compiler knows what abc is.
int pqr(abc t)
{
t.xyz();
return t.x;
}
int main()
{
abc t;
cout<<"Return "<<pqr(t)<<endl;
}
I know you want to use a local class, but what you have set up will not work. Local classes is visible only inside the function it is defined in. If you want to use an instance of abc outside the pqr() function, you have to define the abc class outside the function.
However, if you know that the abc class will be used only within the pqr() function, then a local class can be used. But you do need to fix the friend declaration a little bit in this case.
#include<iostream>
// By the way, "using namespace std" can cause ambiguities.
// See http://www.parashift.com/c++-faq-lite/coding-standards.html#faq-27.5
using namespace std;
// pqr() function defined at global scope
int pqr()
{
// This class visible only within the pqr() function,
// because it is a local class.
class abc
{
int x;
public:
int xyz()
{
return x=4;
}
// Refer to the pqr() function defined at global scope
friend int ::pqr(); // <-- Note :: operator
} t;
t.xyz();
return t.x;
}
int main()
{
cout<<"Return "<<pqr()<<endl;
}
This compiles without warnings on Visual C++ (version 15.00.30729.01 of the compiler).