Template class, static function compile error c++ - 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.

Related

Why do members of a template class need to be parameterized by the parameters of their template class

In page 668 of Stroustrup's book (4th edition - first printing) you`ll find the following example of a template class?
template<typename C>
class String{
public:
String();
...
private:
int sz;
C* ptr;
};
In page 679 the author writes:
Members of a template class are themselves templates parameterized by
the parameters of their template class. When such a member is defined
outside its class, it must explicitly be declared as template. For
example:
template<typename C>
String<C>::String()
:sz(0), ptr(ch)
{
ch[0] = {};
}
There is an obvious error in this example. The variable ch doesn't make any sense above. But that has nothing to do with my question. What I'd like to know is why the constructor above can't be defined without the parameter C, as shown below?
template<typename C>
String::String()
: sz(0), ptr(nullptr)
{
}
String is the name of a template, not a class. A template is not not even a type, so it doesn't have members. A template specialization is a class, however. You need to plug in C in order to specify which specialization it is you are referring to for the purposes of this definition.
Now it just so happens that the definition itself is a template, but that is because you are defining things for a family of specializations. Nevertheless the fact remains that you need to name those specializations explicitly.
Finally, the reason you only need to specify the specialization once is that the template name is treated in a special manner inside the scope of a class template specialization. Inside that scope the template name refers to the the injected class name, to the specialization itself. That's why
template<typename C>
String<C>::String<C>()
:sz(0), ptr(ch)
{
}
... can be written as...
template<typename C>
String<C>::String()
:sz(0), ptr(ch)
{
}
Since String<C> already established the specialization we are referring to, and we are inside its scope, we can use String with its special meaning as the injected class name.
C++ could have been designed with a special rule to make this trivial and common case work like you expect it to. The current rules are more consistent though, as they still work the in more complex cases.
In particular, consider the following :
template<typename C, int I> class String { };
template<typename C> class String<C,0> { String(); };
template<typename C> class String<C,1> { String(); };
This is a class template with two partial specializations.
Now the first ctor is defined as
template<typename C> String<C,0> :: String() { }
You see that the template argument list has one extra argument, ,0 which indicates the specific specialization. Partial specializations vary some, but not all template parameters of the base template. You have to specify which parameters can vary, and which have fixed values.

C++, partial specialization of 2-argument class template: unable to match function definition to an existing declaration

I'm currently implementing a dataset helper class template storing floating point values (Scalar) in a dynamically sized Eigen::Matrix constructed from a vector of different values types (Element) additionally storing a reference to this input vector. Now i want to partially specialize the constructor in the vector value type remaining a template in the scalar type to be explicitly instantiated.
Unfortunately i'm getting "unable to match function definition to an existing declaration" on VS 2010. The code is as simple as:
template <class Scalar, class Element> struct DataSet
{
DataSet(std::vector<Element> const & source);
// several generic member functions here ...
Eigen::Matrix<Scalar, ... > data;
std::vector<Element> const & source;
};
template<class Scalar>
DataSet<Scalar, SomeClass>::DataSet(std::vector<SomeClass> const & input)
{
// special impl for Element==SomeClass ...
}
SomeClass should be automatically be figured out by the compiler, when done right but i tried all meaningful combinations but still getting:
*.cpp(79) C2244 : unable to match function definition to an existing declaration
see declaration of 'DataSet<Scalar, Element>::DataSet'
I was not able to find a matching example by searching the internet yet. Thanks in advance!
EDIT:
To make it more specific, in my real world case i want to be able to define several partial specializations to the constructor with different types for Element e.g:
template<Scalar>
DataSet<Scalar, FirstClass>::DataSet(std::vector<FirstClass> const & first)
: data()
, source(first)
{
// special impl here ...
}
template<Scalar>
DataSet<Scalar, std::shared_ptr<SecondClass> >::DataSet(std::vector<std::shared_ptr<SecondClass> > const & second)
: data()
, source(second)
{
// special impl here ...
}
Redeclaring/specializing the class completely to a certain typename is not desired. Then there is little use to be a template at all. I want the solution as it is, otherwise there might be other strategies to my problem.
FIN:
Since it looks like not being possible to share the type Element between class template and constructor by only specializing the constructor (which is somehow related to an implicit specialization of the class) i removed the reference source from the class template entirely and copied the needed information into a generic container and implemented the constructors via overloads.
When defining your constructor, you didn't explicitly provide both template arguments for its class. That would need to be revised as follows:
template<typename T_Scalar, typename T_Element>
DataSet<T_Scalar, T_Element> // template args for type
::DataSet(std::vector<T_Element> const &input) // but none for constructor
{
// stuff
}
Tangentially related: Unlike methods, template arguments for classes cannot be deduced from constructor calls. That is: until C++17 comes around! woo!
The next stumbling block you faced is that template specialisations do not 'inherit' members from their primary template. It is somewhat intuitive to assume they would, but it's just not so. Until I find an official rationale, I presume it's because template arguments might make certain members totally inapplicable to a specialisation, rendering implicit 'inheritance' problematic. If so, it would've been decided to require full redeclaration / not judged worthwhile to add arcane syntax to specify which primary 'base' members are 'inherited'... when you can simply use real inheritance to ensure they are.
Anyway, what that means is that to get a partial specialisation, you need to declare the whole thing - in this case, the class and its constructor - before you can specialise that constructor's definition. You hadn't declared these ahead of time, so the compiler rightly complained that it couldn't see a declaration.
// Define specialised class
template<typename T_Scalar>
class DataSet<T_Scalar, SomeClass>
{
public:
// Declare its ctor
DataSet(std::vector<SomeClass> const &);
}
// Implement its ctor
template<typename T_Scalar>
DataSet<T_Scalar, SomeClass> // complete template args
::DataSet(std::vector<SomeClass> const &input)
{
// stuff
}
See my working example of an equivalent template class, showing general vs. specialised instantiations.
To add to your original confusion, which is fair! - note that out-of-line definitions can get very complicated indeed if a template class itself contains a template function, because then you need 2 template clauses, e.g.
template<typename TA, typename TB>
class Widget {
template<typename TC>
void accept_gadget(TC &&gadget);
};
template<typename TA, typename TB>
template<typename TC>
Widget<TA, TB>
::accept_gadget(TC &&gadget)
{
/* ... */
}
Something that will help a lot in many contexts, especially including such out-of-line template definitions, is if the proposal to allow namespace class is accepted in a future version. Very sad this didn't make it into C++17... and very odd that it was ever missing in the 1st place!
According to §14.7.3.16:
In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
Still, you can use std::enable_if to partial-specialize your contructor:
template <class Scalar, class Element> struct DataSet
{
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<!std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "Element\n";
}
template <class T>
DataSet(std::vector<T> const & input, std::enable_if_t<std::is_same<T, SomeClass>{}> * = nullptr) {
std::cout << "SomeClass\n";
}
};
But this way is restrictive:
all your conditions must be exclusives
you'll have to modify the code of your class for every new class you want to handle.
Instead, I'd advise you to use a template helper structure:
DataSet(std::vector<Element> const & input) {
Helper<Element>::do_it(input);
}
that you can specialize as you want:
template <class Element>
struct Helper {
static void do_it(std::vector<Element> const & input) {
std::cout << "General form with Element\n";
}
};
template<>
struct Helper<SomeClass> {
static void do_it(std::vector<SomeClass> const & input) {
std::cout << "SomeClass\n";
}
};
template<>
struct Helper<SomeOtherClass> {
static void do_it(std::vector<SomeOtherClass> const & input) {
std::cout << "SomeOtherClass\n";
}
};
...

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)

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