How do friend classes interact with each other - c++

I have two simple class that I made just to understand how friend class works. I am confused as to why this doesn't compile and also would the Linear class have access to the struct inside Queues class?
Linear.h
template<typename k, typename v >
class Linear
{
public:
//Can I create a instance of Queues here if the code did compile?
private:
};
Linear.cpp
#include "Linear.h"
Queues.h
#include "Linear.h"
template<typename k, typename v >
class Linear;
template<typename x>
class Queues
{
public:
private:
struct Nodes{
int n;
};
//Does this mean I am giving Linear class access to all of my Queues class variable or is it the opposite ?
friend class Linear<k,v>;
};
Queues.cpp
#include"Queues.h"
My errors are
Queues.h:15: error: `k' was not declared in this scope
Queues.h:15: error: `v' was not declared in this scope
Queues.h:15: error: template argument 1 is invalid
Queues.h:15: error: template argument 2 is invalid
Queues.h:15: error: friend declaration does not name a class or function

To answer your initial question:
the friend keyword inside a class let the friend function or class access otherwise private field of the class where the friend constraint is declared.
See this page for a thorough explanation of this language feature.
Regarding the compilation errors in your code:
In this line:
friend class Linear<k,v>;
ask yourself, what is k, where is it defined? Same for v.
Basically, a template is not a class, it's a syntactic construct letting you define a "class of class", meaning that for the template:
template <typename T>
class C { /* ... */ };
you don't have yet a class, but something that will let you define class if you provide it a proper typename. Within the template the typename T is defined, and can be used in place as if it were a real type.
In the following code snippets:
template <typename U>
class C2 {
C<U> x;
/* ... */
};
you define another template, which when instantiated with a given typename will contain an instance of the template C with the same typename. The typename U in the line C<U> x; of the code above, is defined by the including template. However, in your code, k and v don't have such a definition, either in the template where they are being used, or at the top level.
In the same spirit, the following template:
template <typename U>
class C2 {
friend class C<U>;
/* ... */
};
when instantiated, will have the instance of the class template C (again with the same parameter U) as a friend. As far as I know, It is not possible to have class template instances be friend with a given class, for all possible parameters combinations (The C++ language doesn't support existential types yet).
You could, for instance, write something like:
template<typename x>
class Queues
{
public:
private:
struct Nodes{
int x;
};
friend class Linear<x,x>;
};
to restrict the friendliness of Linear to only the instance of that template with x and x, or something like this:
template<typename x,typename k, typename v>
class Queues
{
public:
private:
struct Nodes{
int x;
};
friend class Linear<k,v>;
};
If you want to allow k and v to be defined ad lib.

Your problem is with templates not with friend classes in that code.
Friend just means that restrictions against access to private and protected are removed for that class. As if the word private in the class was public, basically.
Do try to submit code with one problem and which you understand all but one thing.

Related

Timing of C++template specialization and constexpr function execution [duplicate]

Note: this seems to be a repost of a problem: C++ - Overload templated class method with a partial specilization of that method
I have boiled down a problem I am having with C++ template specialization down to a simple case.
It consists of a simple 2-parameter template class Thing, where I would like to specialize Thing<A,B>::doSomething() for B=int.
#include <cstdio>
// A 3-parameter template class.
template <class A, class B>
class Thing
{
public:
Thing(A a, B b) : a_(a), b_(b) {}
B doSomething();
private:
A a_;
B b_;
};
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return b_;
}
// This specialization does not work!
template <class A>
int Thing<A,int>::doSomething()
{
return b_+1;
}
int main() {
// Setup our thing.
Thing<double,int> thing(1.0,2);
// This doesn't compile - but works with the generic case.
printf("Expecting 3, and getting %i\n", thing.doSomething());
// Clean up.
return 0;
}
Unfortunately, g++ exits with the error:
partial_specialization.cpp:30: error: invalid use of incomplete type ‘class Thing<A, int>’
partial_specialization.cpp:8: error: declaration of ‘class Thing<A, int>’
The clang++ compiler is a bit more verbose, but has the same problem:
partial_specialization.cpp:30:19: error: nested name specifier 'Thing<A, int>::' for declaration does not
refer into a class, class template or class template partial specialization
int Thing<A,int>::doSomething()
~~~~~~~~~~~~~~^
partial_specialization.cpp:32:12: error: use of undeclared identifier 'b_'
return b_+1;
^
2 errors generated.
I have read and understood that partial template specializations on functions aren't allowed - but I thought I was partially specializing over classes of Thing in this case.
Any ideas?
What I did: A workaround, as determined from the link provided by the accepted answer:
template< class T >
inline T foo( T const & v ) { return v; }
template<>
inline int foo( int const & v ) { return v+1; }
// The generic case works as expected.
template <class A, class B>
B Thing<A,B>::doSomething()
{
return foo(b_);
}
Partial specialization of a function template, whether it is member function template or stand-alone function template, is not allowed by the Standard:
template<typename T, typename U> void f() {} //okay - primary template
template<typename T> void f<T,int>() {} //error - partial specialization
template<> void f<unsigned char,int>() {} //okay - full specialization
But you can partially specialize the class template itself. You can do something like this:
template <class A>
class Thing<A,int> //partial specialization of the class template
{
//..
int doSomething();
};
template <class A>
int Thing<A,int>::doSomething() { /* do whatever you want to do here */ }
Note that when you partially specialize a class template, then the template parameter-list of member function (in its definition outside the class), must match the template parameter list of the class template partial specialization. That means, for the above partial specialization of the class template, you cannot define this:
template <class A>
int Thing<A,double>::doSomething(); //error
Its not allowed, because the template parameter-list in function definition didn't match the template parameter-list of the class template partial specialization. §14.5.4.3/1 from the Standard (2003) says,
The template parameter list of a member of a class template partial specialization shall match the template parameter list of the class template partial specialization.[...]
For more on this, read my answer here:
C++ - Overload templated class method with a partial specilization of that method
So what is the solution? Would you partially specialize your class along with all the repetitive work?
A simple solution would be work delegation, instead of partially specializing the class template. Write a stand-alone function template and specialize this as:
template <class B>
B doTheActualSomething(B & b) { return b; }
template <>
int doTheActualSomething<int>(int & b) { return b + 1; }
And then call this function template from doSomething() member function as:
template <class A, class B>
B Thing<A,B>::doSomething() { return doTheActualSomething<B>(b_); }
Since in your particular case, doTheActualSomething needs to know the value of only one member, namely b_, the above solution is fine, as you can pass the value to the function as argument whose type is the template type argument B, and specialization for int is possible being it full-specialization.
But imagine if it needs to access multiple members, type of each depends on the template type argument-list, then defining a stand-alone function template wouldn't solve the problem, because now there will be more than one type argument to the function template, and you cannot partially specialize the function for just, say, one type (as its not allowed).
So in this case you can define a class template instead, which defines a static non-template member function doTheActualSomething. Here is how:
template<typename A, typename B>
struct Worker
{
B doTheActualSomething(Thing<A,B> *thing)
{
return thing->b_;
}
};
//partial specialization of the class template itself, for B = int
template<typename A>
struct Worker<A,int>
{
int doTheActualSomething(Thing<A,int> *thing)
{
return thing->b_ + 1;
}
};
Notice that you can use thing pointer to access any member of the class. Of course, if it needs to access private members, then you've to make struct Worker a friend of Thing class template, as:
//forward class template declaration
template<typename T, typename U> struct Worker
template <class A, class B>
class Thing
{
template<typename T, typename U> friend struct Worker; //make it friend
//...
};
Now delegate the work to the friend as:
template <class A, class B>
B Thing<A,B>::doSomething()
{
return Worker<A,B>::doTheActualSomething(this); //delegate work
}
Two points to be noted here:
In this solution, doTheActualSomething is not a member function template. Its not enclosing class which is template. Hence we can partially specialize the class template anytime, to get the desired effect of the partial member function template specialization.
Since we pass this pointer as argument to the function, we can access any member of the class Thing<A,B>, even private members, as Worker<T,U> is also a friend.
Complete online demo : http://www.ideone.com/uEQ4S
Now there is still a chance of improvement. Now all instantiations of Worker class template are friends of all instantiation of Thing class template. So we can restrict this many-to-many friendship as:
template <class A, class B>
class Thing
{
friend struct Worker<A,B>; //make it friend
//...
};
Now only one instantiation of Worker class template is a friend of one instantiation of Thing class template. That is one-to-one friendship. That is, Worker<A,B> is a friend of Thing<A,B>. Worker<A,B> is NOT a friend of Thing<A,C>.
This change requires us to write the code in somewhat different order. See the complete demo, with all the ordering of class and function definitions and all:
http://www.ideone.com/6a1Ih
This is a very often found problem, and there is a surprisingly simple solution. I will show it in an artificial example, because it's more clearer than to use your code, and you will have to understand it to adapt it to your code
template<typename A, typename B>
struct TwoTypes { };
template<typename A, typename B>
struct X {
/* forwards ... */
void f() { fImpl(TwoTypes<A, B>()); }
/* special overload for <A, int> */
template<typename A1>
void fImpl(TwoTypes<A1, int>) {
/* ... */
}
/* generic */
template<typename A1, typename B1>
void fImpl(TwoTypes<A1, B1>) {
/* ... */
}
};
Explicitly specializing functions is never (almost never?) the right way. In my work as a programmer, I've never explicitly specialized a function template. Overloading and partial ordering is superior.

accessing definitions from sub class in templated class

I have trouble to build a class which itself contains a subclass which self derives from class which needs template parameters from the top class. Sound horrible and it is indeed deep inside some MTP construction. But have a look on a simple example which I could shrink from the real code.
I leave the names as is in my original source. They are not important here.
template <typename ... T>
class ConstructAll: public T...
{
public:
using ConstructorParms = int;
using BASES_T = ConstructAll<T...>;
ConstructAll(int){}
};
template <typename T>
class WithTemplate
{
};
class WithoutTemplate
{
};
template <typename X>
class CircuitFromNetlist
{
private:
class SerialReader: public ConstructAll<
WithTemplate<X> // use this-> don't compile
//WithoutTemplate // but this works
>
{
public:
SerialReader( typename BASES_T::ConstructorParms p): BASES_T( p ) {}
};
public:
CircuitFromNetlist()
{
SerialReader ser{1};
}
};
int main()
{
CircuitFromNetlist<int> c;
}
If I use WithTemplate<X>it did not compile and runs into:
main.cpp:31:40: error: 'BASES_T' has not been declared
SerialReader( typename BASES_T::ConstructorParms p): BASES_T( p ) {}
^~~~~~~
main.cpp: In constructor 'CircuitFromNetlist::SerialReader::SerialReader(int)':
main.cpp:31:70: error: class 'CircuitFromNetlist::SerialReader' does not have any field named 'BASES_T'
SerialReader( typename BASES_T::ConstructorParms p): BASES_T( p ) {}
If I flip the code to use non templated class it seems to work.
Some idea to get the thing working?
What you're seeing here is actually correct behavior according to the C++11 standard:
In the definition of a class or class template, if a base class depends on a template-parameter, the base class scope is not examined during unqualified name lookup either at the point of definition of the class template or member or during an instantiation of the class template or member. -- [temp.dep] (emphasis mine)
When you inherit from ConstructAll<WithoutTemplate>, the base class does not depend on the template parameter X, but obviously inheriting from ConstructAll<WithTemplate<X>> the base class does depend on this template parameter.
You will have to explicitly refer to the type as typename ConstructAll<WithTemplate<X>>::BASES_T.

How to refer to a type defined in a derived class passed as a template argument?

Consider the following example:
template <typename T>
class A {
private:
typedef typename T::C C;
};
template <typename T>
class B : public A<B<T>> {
public:
typedef T C;
};
int main() {
B<int> b;
}
Compiling it with GCC gives the following error:
test.cc:5:23: error: no type named 'C' in 'B<int>'
typedef typename T::C C;
~~~~~~~~~~~~^
test.cc:9:18: note: in instantiation of template class 'A<B<int> >' requested here
class B : public A<B<T>> {
^
test.cc:15:10: note: in instantiation of template class 'B<int>' requested here
B<int> b;
^
Why does compiler give an error if B::C is defined and how to fix it?
At this point,
class B : public A<B<T>> {
… class B is incomplete. Class A can't look inside it.
The C type definition inside B is accessible from that point inside B, and on. It's also available inside function bodies in B because you can regard a function definition inside the class definition as a shorthand for placing it after the class. But an incomplete class contains nothing as viewed from outside: all that outside code can do is form pointers and references and use the class as template argument.
template< class C >
using Ungood = typename C::Number;
struct S
{
void foo() { Number x; (void) x; } // OK
Ungood<S> uhuh; //! Nyet.
using Number = double;
};
auto main() -> int {}
You can fix your code by changing the design. The most obvious is to pass the type as a separate template argument. But depending on what you're trying to achieve it may be that the inheritance you currently have, isn't really needed or even useful.
You can't because you're in a chicken-egg paradox. The definition of the base requires knowledge of the definition of the derived, which needs the definition of the base to complete. You simply have to come up with an alternative. One example would be to use an external metafunction to communicate the needed type to whoever needs it. Hopefully that's not in any part of the definition of the base's members or you're probably screwed.
Other alternative is to pass T as a second parameter.
You can't do that because of this:
A class is considered defined after the closing brace of its class-specifier has been seen [...]
And a few exceptions, none of which are valid in your case.
In other terms, you must consider your derived class as not fully defined when you try to use it in your base class to access the type C.
Anyway, you can exploit the fact that your derived class is a template class and do this:
template <typename T>
class A;
template <template<typename> class D, typename T>
class A<D<T>> {
private:
using C = T;
};
Aa you can see, I've not given a definition for the primary template class, thus only the specialization for template classes can be used.
Not sure this is the OP's real case, but it's the case in the example in the question.

C++ Template trouble

I would appreciate some assistance in a (for my level anyways) rather complicated template problem.
Let me explain my 'system' first.
Modeling a basic audio mixing and streaming system, it has three building components:
A Buffer, from which the Player will process data from.
Since they are directly connected by data, their data needs to by of the same type. Thus Buffer<T> ~ Player<T> , here the templates must match.
These are wrapped in Manager, who will eventually manage all the incoming buffers into one player.
Now, both Buffers and Players would need some different implementations, thus they are represented by generic interfaces as iPlayer and iBuffer.
My goal is to be able to declare a manager like this:
simple_manager<simple_player<float>>;
or failing this at least
simple_manager<simple_player , float>;
Since im not sure the first one even has a solution, my attempt at the second was thus:
template <typename K>
class iManager {
private:
K player;
};
template <template <typename> class C , typename T>
class simple_manager : iManager< C<T> > {
public:
void play(iBuffer<T> & _buffer,const audio_descriptor ad, bool * condition){
player.play(_buffer,ad,condition);
}
};
As you can see, in the concrete class, T marks the type of the data to be manipulatod, while C is the concrete class of player i wish to use.
The interface has only one template which marks the concrete player class again. So K ~ C<T>
This does not compile with (only) the following error:
simple_manager.cpp: In member function ‘void simple_manager<C, T>::play(iBuffer<T>&, audio_descriptor, bool*)’:
simple_manager.cpp:18:12: error: ‘player’ was not declared in this scope
player.play(_buffer,ad,condition);
^~~~~~
And i do not know what causes this. Can the compiler not deduce that T must be inherited from iPlayer, since iPlayer must implement a play() method.
I can get it to actually work if I define simple_manager like this:
class simple_manager : iManager< simple_player<float> > {...}
but it still won't work with:
class simple_manager : iManager< simple_player<T> > {...}
I am stumped. If i had <T extends iPlayer> from Java, this would work, but compilation-time templating is a tougher nut i guess.
Any help would be greatly appreciated!
The first issue is that player is inaccessible from the derived class because it's marked private instead of protected. You could make it protected or add some protected member function to access it:
template <typename K>
class iManager {
protected:
K player;
};
This still won't work, however, because iManager<C<T>> is a dependent base class, so its members are hidden from unqualified name lookup. To get around this, you can access it through the this pointer:
void play(iBuffer<T> & _buffer,const audio_descriptor ad, bool * condition){
this->player.play(_buffer,ad,condition);
}
To get the nice usage in your first example, you could write a trait to extract a template argument from given type:
template <typename T> struct extract_inner;
template <template <typename> class C, typename T>
struct extract_inner<C<T>> { using type = T; };
template <typename T>
using extract_inner_t = typename extract_inner<T>::type;
Then that can be used to supply the correct argument to iBuffer:
template <typename T>
class simple_manager : iManager< T > {
public:
void play(iBuffer<extract_inner_t<T>> & _buffer,
const audio_descriptor ad, bool * condition){
this->player.play(_buffer,ad,condition);
}
};
Live demo
Your problem is quite simple.
You got almost all the syntax right, but you miss one thing: the this keyword.
When you extend a class that depending on a template parameter, this become kind of a dependent name. Since the base class is a template that depends on the a template parameter on your child, the compiler must know which name come from the base and which does not. If the compiler would not request to remove the ambiguity, one could specialize your base class, throw a bunch on names and make your child class use them.
To remove the ambiguity, simply add this-> keyword in front of the name that come from the base class:
template <template <typename> class C , typename T>
struct simple_manager : iManager< C<T> > {
void play(iBuffer<T> & _buffer,const audio_descriptor ad, bool * condition){
this->player.play(_buffer,ad,condition);
}
};

Specialization of a template to a nested class type

Is there anyway to specialize a trait template for a nested class? I've tried it in the three places noted below, each with the given error. I've seen questions regarding specializing nested template classes, but that's not what I'm trying to do here-- I'm trying to specialize a trait class that is used by the nested class.
The TraitUser class makes use of the definitions within the Trait as specialized to a specific type T. Perhaps most relevantly, it uses a trait member to initialize a base class.
template<T>
class TraitUser:public X<typename Trait<T>::Type>
{
//Trait<T> gets used in here
};
//class A;
//class A::B; <-incomplete type used in nested name
//template<>
//struct Trait<A::B>
//{};
class A
{
private:
//class B;
//template<> <-explicit specialization at class scope
//struct Trait<B>
//{};
class B:TraitUser<B>
{};
};
//template<> <- specialization after instantiation
//struct Trait<A::B>
//{};
It looks like the root of the trouble is not being able to forward declare a nested class and also not being able to define a specialization inside a class declaration.
I'm trying this under clang using C++11.
There's some complicated declaration ordering here:
template <class T>
struct Trait;
template <class T>
struct X
{};
template<class T>
class TraitUser:public X<typename Trait<T>::Type>
{
//Trait<T> gets used in here
};
class A
{
private:
class B;
};
template<>
struct Trait<A::B>
{
typedef int Type;
};
class A::B : public TraitUser<B>
{};