Protected member is unknown for derived class - c++

I found an open source class library for Graphs. When I included it in my project it has many errors and I tried to fix them. But there is a compile error that I can not solve it.
Base class:
template <typename K, typename W, typename T>
class _base_graph
{
//...
protected:
std::map<K, T> nod;
std::list<edge> edg;
};
Derived class:
template <typename K, typename T = void*>
class graph : public _base_graph<K, void*, T>
{
//...
public:
void add_edge(const K& k1, const K& k2);
};
Method body:
template <typename K, typename T>
void graph<K, T>::add_edge(const K& k1, const K& k2)
{
if (nod.find(k1) == nod.end() || nod.find(k2) == nod.end()) // <-- error!!
throw std::string("add_edge: Node does not exist");
// ...
}
But my gcc compiler show me an error:
error: ‘nod’ was not declared in this scope
You can find and test mycode in this online compiler.

You need
this->nod.find(k2);
or
_base_graph<K, void*, T>::nod.find ....;
The base and the derived classes are templates, and in your code nod is a non-dependent name, and so is looked up at the point of graph's declaration. This is the first phase of the two-phase lookup. At this stage, it is impossible for the compiler (provided it follows the name lookup rules of the standard) to know what nod means, because it does not consider the base class until the second phase. So it is necessary to tell the compiler that nod should be looked up in the second phase. To do this, we explicitly tell it that nod is in a base class by using one of the forms above.
The reason for this behaviour is that at the point of the derived class' definition, it should not possible to know what _base_graph<K, void*, T>:: contains, to allow for specializations of the template that add and even hide names. So the trick above makes sure that the names are looked up at the point of the derived class' instantiation, when all the information is available.
In summary, there are two issues in play here:
nod is not a dependent name, so it would be looked up in the first phase.
The base class template, which declared nod, is not available until the second phase, so the name cannot be resolved.
By using this->nod or _base_graph<K, void*, T>::nod, we are explicitly dealing with a dependent name, forcing the lookup to take place in the second phase.
See points 7 to 10 here.
Thanks to #DavidRodriguez-dribeas for clarifying some of the finer points of the two phase look-up.

nod is a member of a dependent base (one that depends on template parameters). You either need to qualify the call with the name of the base, e.g. _base_graph<K, void*, T>::nod or with this->nod.
Alternatively you can also bring in names with using _base_graph<K, void*, T>::nod in either function or class scope.

Related

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);
}
};

Declaring a static pointer to an inner class object in a template

I'm trying to create a simple template binary search tree for practice, and I currently have something like the following in a header file:
template <class T_Satellite, class T_Key>
class bst {
struct bst_node;
static const bst_node* nullnode;
}
My problem currently stems from trying to define nullnode in the cpp file. I've tried:
template <class T_Satellite, class T_Key>
const bst<T_Satellite, T_Key>::bst_node * bst::nullnode = bst_node(nullptr, nullptr);
and
template <class T_Satellite, class T_Key>
const bst<T_Satellite, T_Key>::bst_node * bst::nullnode(nullptr, nullptr);
But neither seem to work at all. I have a definition for bst_node in my cpp file as well. The compiler spits out that
'std::bst<T_Satellite,T_Key>::nullnode' : static data member cannot be initialized via derived class'
in the first example as well as
'std::bst<T_Satellite,T_Key>::bst_node' : dependent name is not a type.
Any ideas?
You need to use the typename keyword:
template <class T_Satellite, class T_Key>
const typename bst<T_Satellite, T_Key>::bst_node * bst::nullnode = bst_node(nullptr, nullptr);
The error message referencing "dependent name" is the clue. typename must be used for all dependent names that reference a type. A name is "dependent" if it involves an unbound template parameter.
Additionally, you'll almost certainly need to move this into your header file since the name will need to be instantiated with the actual used template parameters unless you're doing explicit instantiation.
Dependent names are those that depend on a template parameter. Dependent names are not treated as types to avoid ambiguity - the compiler doesn't have a way of knowing if the name refers to a member or a type. This is where you need to use the typename keyword.
Refer to the type bst_node as
template <class T_Satellite, class T_Key>
const typename bst<T_Satellite, T_Key>::bst_node

C++ templates: Returning list::iterator

How can I make the following code work? During compilation I get an error telling me that the searchForResource function has no return type.
template<class T>
class ResourceManager
{
private:
struct ResourceWrapper;
std::list<ResourceWrapper*> resources_; // This compiles fine
std::list<ResourceWrapper*>::iterator // Error occurs here
searchForResource(const std::string& file);
};
Also, is this how I would define the searchForResource function?
template<class t>
std::list<typename ResourceManager<T>::ResourceWrapper*>::iterator
ResourceManager<T>::searchForResource(const std::string& file)
{
// ...
}
std::list<ResourceWrapper*>::iterator is hard for the compiler to understand. Prefix it with typename in both the implementation and the declaration to let the compiler know that it's a type.
Like so:
typename std::list<ResourceWrapper*>::iterator searchForResource(const std::string& file);
template<class T>
class ResourceManager
{
private:
struct ResourceWrapper;
std::list<ResourceWrapper*> resources_;
// | typename lost here
// V
typename std::list<ResourceWrapper*>::iterator
searchForResource(const std::string& file);
};
template<class T>
// | typename lost here asterisk lost here |
// V V
typename std::list<typename ResourceManager<T>::ResourceWrapper*>::iterator
ResourceManager<T>::searchForResource(const std::string& file)
{
return ...
}
There is a rule of thumb to avoid such compilation errors.
Whenever you are declaring a variable or function, with a template followed by scope resolution operator :: then always put a keyword typename in front of the definition.
For example,
MyNameSpace::MyClass<T> x; // Ok; because template is NOT followed by scope resolution
MyNameSpace::MyClass<T>::MyType x; // Error; MyType can be a variable or a type; so put typename ahead
Same thing is applicable to function declaration also.
I think you're missing a typename keyword.
The problem is that ResourceWrapper is a dependent name *(it's definition depends on the type argument T), and that makes std::list< ResourceWrapper * > a dependent type name. Templates are checked in two passes, during the first pass, correctness of the template without actual type substitution is checked. Now when you type std::list< ResourceWrapper* >::iterator the compiler cannot know upfront that iterator is in fact a type and not an static attribute or member of the class std::list< ResourceWrapper* > because of the type being dependent and the T not yet being substituted.
You have to hint the compiler as to inform it that the iterator is indeed a type by using the typename keyword, as others have already mentioned before:
typename std::list< ResourceWrapper* >::iterator
Without seeing the rest of the code, I cannot say, but it seems as if ResourceWrapper should actually not be a dependent type on T. If it is in fact non-dependent, you should move the type outside of the class template. in that case, the typename will no longer be required:
struct ResourceWrapper;
template <typename T>
class ResourceManager {
std::list<ResourceWrapper*>::iterator searchForResource(const std::string& file);
...
Because it is defined outside of the template there is a single definition for all possible instantiations of the ResourceManager template, now ResourceWrapper is no longer dependent on T, and typename is no longer needed (nor correct).
* Why is ResourceWrapper dependent and how could this affect the code.
The reason that ResourceWrapper is dependent on the type T is easier seen by discussing the fully qualified name: ::ResourceManager<T>::ResourceWrapper. The T is part of the type, and as such T affects the actual definition of ResourceWrapper. This is somehow a contrived example in that you can arguably say that if the compiler is parsing this particular template, then it must know that ResourceWrapper is a type, and thus that std::list< ResourceWrapper*>::iterator is a type... and here is the problem. There is no particular reason not to have an specialization of the std::list template for a particular instantiation of ResourceManager:
namespace std { // you should in general not add things to the std namespace!
// but the implementation can
template <>
struct list< ResourceManager<int>::ResourceWrapper > {
static const int iterator = 5;
...
};
}
Again, contrived, but the compiler cannot possibly know upfront while parsing the template that such an specialization will not be present before you actually instantiate the template with a particular type.
you have forward declaration of ResourceWrapper struct which is good enough for the line that compiles fine, but you are getting the error because at that point compiler needs full type declaration for ResourceWrapper struct. (possibly your answer, this code actually compiles fine with VS2008)

Template class, static function compile error c++

I have the following function defined inside my linked list class. The declaration in the header file looks like this:
template <typename T>
class RingBuffer
{
...//stuff
static BLink * NewLink (const T&); // allocator
};
BLink is a "link" class within the RingBuffer class. The following implementation code:
template <typename T>
RingBuffer<T>::BLink * RingBuffer<T>::NewLink( const T& t ) // this is line 114
{
// create a new link in linked list
....
....
}
Is giving me this compile error:
./ringbuff.cpp:114: error: expected constructor, destructor, or type conversion before â*â token
I am stumped as to why it it needs an expected constructor, destructor, or type conversion before the return value.
The problem here is that you are referring to a nested dependent type name (i.e. BLink is nested inside RingBuffer which is dependent on a template parameter)
You need to help your compiler a little in this case by stating that RingBuffer<T>::BLink is an actual type name. You do this by using the typename keyword.
template <typename T>
typename RingBuffer<T>::BLink * RingBuffer<T>::NewLink(const T& t)
{
// ...
}
Explanation:
The compiler cannot know if RingBuffer<T>::BLink is a type name or a static member until the template parameter T is known. When the compiler parses your function template T is not known and the rule to solve the ambiguity is to default to "this is not a type name".
Another short example (blatantly copied from Scott Meyers' Effective C++):
template<typename C>
void print2nd(const C& container)
{
C::const_iterator * x;
…
}
This maybe illustrates the problem a little better as it's more compact. As already said it's not clear for the parser whether C::const_iterator is a type name or a static data member as it doesn't know what C is when it parses this part of the code (it may know at a later point in time when the template is actually instantiated). So to ease the compiler implementers' lives this ambiguity is resolved to "not a type name" and if the programmer wants to use a type name which is nested inside anything that is dependent on a template parameter he/she has to use the typename keyword in front of the name to let the compiler know that it should be treated as a type name.
Unfortunately there is an exception to that rule regarding nested dependent type names when using them inside a base class list or the base class identifier in a member initialization list.
template<typename T>
struct Base {
struct Nested {
Nested(int) {}
};
};
template<typename T>
struct Derived : public Base<T>::Nested { // typename not allowed here
Derived(int i)
: Base<T>::Nested(i) // nor here
{}
};
Btw: You should set your console client's charset to UTF-8, so you get ‘*’ instead of â*â.
compiler message is a little bit misleading.
In basically signifies syntax/parsing error.
Make sure the prototype is visible in compilation file, make sure you ring buffer is declared as template. and as other people have said, check the semi-column after class declaration.

Officially, what is typename for?

On occasion I've seen some really indecipherable error messages spit out by gcc when using templates... Specifically, I've had problems where seemingly correct declarations were causing very strange compile errors that magically went away by prefixing the typename keyword to the beginning of the declaration... (For example, just last week, I was declaring two iterators as members of another templated class and I had to do this)...
What's the story on typename?
Following is the quote from Josuttis book:
The keyword typename was introduced to
specify that the identifier that
follows is a type. Consider the
following example:
template <class T>
Class MyClass
{
typename T::SubType * ptr;
...
};
Here, typename is used to clarify that
SubType is a type of class T. Thus,
ptr is a pointer to the type
T::SubType. Without typename, SubType
would be considered a static member.
Thus
T::SubType * ptr
would be a multiplication of value
SubType of type T with ptr.
Stan Lippman's BLog post suggests :-
Stroustrup reused the existing class
keyword to specify a type parameter
rather than introduce a new keyword
that might of course break existing
programs. It wasn't that a new keyword
wasn't considered -- just that it
wasn't considered necessary given its
potential disruption. And up until the
ISO-C++ standard, this was the only
way to declare a type parameter.
So basically Stroustrup reused class keyword without introducing a new keyword which is changed afterwards in the standard for the following reasons
As the example given
template <class T>
class Demonstration {
public:
void method() {
T::A *aObj; // oops …
// …
};
language grammar misinterprets T::A *aObj; as an arithmetic expression so a new keyword is introduced called typename
typename T::A* a6;
it instructs the compiler to treat the subsequent statement as a declaration.
Since the keyword was on the payroll,
heck, why not fix the confusion caused
by the original decision to reuse the
class keyword.
Thats why we have both
You can have a look at this post, it will definitely help you, I just extracted from it as much as I could
Consider the code
template<class T> somefunction( T * arg )
{
T::sometype x; // broken
.
.
Unfortunately, the compiler is not required to be psychic, and doesn't know whether T::sometype will end up referring to a type name or a static member of T. So, one uses typename to tell it:
template<class T> somefunction( T * arg )
{
typename T::sometype x; // works!
.
.
In some situations where you refer to a member of so called dependent type (meaning "dependent on template parameter"), the compiler cannot always unambiguously deduce the semantic meaning of the resultant construct, because it doesn't know what kind of name that is (i.e. whether it is a name of a type, a name of a data member or name of something else). In cases like that you have to disambiguate the situation by explicitly telling the compiler that the name belongs to a typename defined as a member of that dependent type.
For example
template <class T> struct S {
typename T::type i;
};
In this example the keyword typename in necessary for the code to compile.
The same thing happens when you want to refer to a template member of dependent type, i.e. to a name that designates a template. You also have to help the compiler by using the keyword template, although it is placed differently
template <class T> struct S {
T::template ptr<int> p;
};
In some cases it might be necessary to use both
template <class T> struct S {
typename T::template ptr<int>::type i;
};
(if I got the syntax correctly).
Of course, another role of the keyword typename is to be used in template parameter declarations.
The secret lies in the fact that a template can be specialized for some types. This means it also can define the interface completely different for several types. For example you can write:
template<typename T>
struct test {
typedef T* ptr;
};
template<> // complete specialization
struct test<int> { // for the case T is int
T* ptr;
};
One might ask why is this useful and indeed: That really looks useless. But take in mind that for example std::vector<bool> the reference type looks completely different than for other Ts. Admittedly it doesn't change the kind of reference from a type to something different but nevertheless it could happen.
Now what happens if you write your own templates using this test template. Something like this
template<typename T>
void print(T& x) {
test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
it seems to be ok for you because you expect that test<T>::ptr is a type. But the compiler doesn't know and in deed he is even advised by the standard to expect the opposite, test<T>::ptr isn't a type. To tell the compiler what you expect you have to add a typename before. The correct template looks like this
template<typename T>
void print(T& x) {
typename test<T>::ptr p = &x;
std::cout << *p << std::endl;
}
Bottom line: You have to add typename before whenever you use a nested type of a template in your templates. (Of course only if a template parameter of your template is used for that inner template.)
Two uses:
As a template argument keyword (instead of class)
A typename keyword tells the compiler that an identifier is a type (rather than a static member variable)
template <typename T> class X // [1]
{
typename T::Y _member; // [2]
}
I think all of the answers have mentioned that the typename keyword, is used in two different cases:
a) When declaring a template type parameter. e.g.
template<class T> class MyClass{}; // these two cases are
template<typename T> class MyNewClass{}; // exactly the same.
Which there is no difference between them and they are EXACTLY the same.
b) Before using a nested dependent type name for a template.
template<class T>
void foo(const T & param)
{
typename T::NestedType * value; // we should use typename here
}
Which not using typename leads to parsing/compilation errors.
What I want to add to the second case, as mentioned in Scot Meyers book Effective C++, is that there is an exception of using typename before a nested dependant type name. The exception is that if you use the nested dependant type name either as a base class or in a member initialization list, you should not use typename there:
template<class T>
class D : public B<T>::NestedType // No need for typename here
{
public:
D(std::string str) : B<T>::NestedType(str) // No need for typename here
{
typename B<T>::AnotherNestedType * x; // typename is needed here
}
}
Note: Using typename for the second case (i.e. before nested dependent type name) is not needed since C++20.
#include <iostream>
class A {
public:
typedef int my_t;
};
template <class T>
class B {
public:
// T::my_t *ptr; // It will produce compilation error
typename T::my_t *ptr; // It will output 5
};
int main() {
B<A> b;
int my_int = 5;
b.ptr = &my_int;
std::cout << *b.ptr;
std::cin.ignore();
return 0;
}