I am trying to do the following:
template <class T>
std::ifstream& operator>> (std::ifstream& fin, List<T> l)
{
T temp;
l.resize(0);
fin >> ignore(1,'\t');
for(ListIterator<T> i=l.begin();i!=l.end();i++)
{
fin >> ignore(1,'\t') >> temp;
l.push_back(temp);
}
return fin;
}
I have to read all the contents from a file. Each field is separated by '\t' character, so I have to ignore the '\t' characters.
The error log is the following:
/home/ramy/Documents/C++/Prova/Util.h||In function ‘std::ifstream& Util::operator>> (std::ifstream&, Util::List<T>)’:|
/home/ramy/Documents/C++/Prova/Util.h|431|error: there are no arguments to ‘ignore’ that depend on a template parameter, so a declaration of ‘ignore’ must be available|
/home/ramy/Documents/C++/Prova/Util.h|431|note: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)|
||=== Build finished: 1 errors, 0 warnings ===|
For builtin types, argument dependent lookup (ADL) is not performed, therefore, an ignore symbol must be "imported" into the current namespace.
You can, for example, do this; from most preferred to least preferred (i.e. to most intrusive and name polluting):
foobar::ignore (...)
using foobar::ignore; ignore(...);
using namespace foobar; ignore(...);
The error message comes up like this because in templates, you also enter the realm of dependent names and Two Phase Lookup. Names that depend on a template parameter, e.g.
template <typename T> void foo() {
T x;
x.frobnicate();
}
are looked up in phase 2, which is upon instantiation. Names that do not depend on template parameters, like
class Foo {};
template <typename T> void foo() {
Foo foo;
foo.frobnicate();
}
must be resolvable in the first phase.
This separation helps template authors to find bugs earlier and to find correct symbols, and it helps making templates more generic. For example, in C# generics, everything must be resolvable, which puts rather stringent limits on their flexibility (because everything that may be used by a generic must be defined). Oppositely, some old C++ compilers resolved in phase 2 only, i.e. at instantiation time, which had some subtle consequences for lookup and error finding.
The C++ 2-phase model combines the best of the eager-model (C#) and the lazy-model (some old C++ compilers).
For an easier answer, see
https://web.archive.org/web/20130423054841/http://www.agapow.net/programming/cpp/no-arguments-that-depend-on-a-template-parameter
TL;DR: replace ignore() with this->ignore() and your problem will go away.
The error message means that there is no definition of ignore that the compiler can use at this point. It is exactly the same error that you get if you do:
void f() {
g();
}
void g() {}
... even if it looks very different. Note that there is no ADL issue here as the other answers say. The reason that the error message is so convoluted is because of the way that templates are processed by the compiler.
Templates are processed in two passes, during the first pass everything that is not dependent on the instantiating type must be verified without performing the type substitution, during this pass every non-dependent name must be checked, and in this case the compiler has failed to resolve ignore with the declarations available at the place of definition of the template.
If the expression depended on the type arguments to the template, it would not need to be fully resolved during the first pass and it would be tried again after type substitution, with the declarations available at the place of instantiation.
I've had the same problem and I've fixed it by changing include order.
As phresnel says, the compiler cannot resolve that on the 1st phase, which in my case was because the header with the problematic template method was included before the one with the inner method that couldn't be resolved.
Adding the needed header include removed the error for me. Hope this helps someone else.
I don't know about the weather your problem is solved or not and I hope it would have.
Whenever I face the problem of "There are no arguments that depend on a template parameter" I override the method and call the parent class member function.
To show what I mean consider a class below which is template class ADT
template <typename DataTypeOfNode>
class LinearList
{
public:
LinearList(){}
void addAtBeg(DataTypeOfNode data) {
//Inside implementation....
}
DataTypeOfNode removeFromFront() {
//Inside implementation....
}
// And many more useful methods
~LinearList(){}
};
Now if you inherit this class with a base class say "PriorityQueue" like this
template <typename DataTypeOfNode>
class PriorityQueue : public LinearList<DataTypeOfNode>
{
public:
void enqueue(DataTypeOfNode data){
addAtBeg(data);
}
DataTypeOfNode dequeue(){
return removeFromFront() ;
}
PriorityQueue(){}
~PriorityQueue(){}
};
After compliling you will get error like "There are no arguments that depend on a template parameter" for removeFromFront() and addAtBeg() methods becaouse they have template parameters.
To fix this error you just need to override these methods and call the parent class methods like this
template <typename DataTypeOfNode>
class PriorityQueue : public LinearList<DataTypeOfNode>
{
public:
//Calling parent class methods
void addAtBeg(DataTypeOfNode data){
LinearList<DataTypeOfNode>::addAtBeg(data) ;
}
DataTypeOfNode removeFromFront(){
return LinearList<DataTypeOfNode>::removeFromFront() ;
}
void enqueue(DataTypeOfNode data){
addAtBeg(data);
}
DataTypeOfNode dequeue(){
return removeFromFront() ;
}
PriorityQueue(){}
~PriorityQueue(){}
};
It means that ignore cannot be found by the compiler and ADL cannot kick in. This means that there is no suitably-scoped ignore function.
Related
I am using g++ compiler. I wrote the following code which has a template class definition. The class has a struct data-type called node which has elements a and b of the generic type. The class has one function called print which prints p.h where p is a variable of type node of the class object. The compiler does not show any errors although 'h' is not an element of struct node. Why is that?
#include<iostream>
#include<cstdlib>
using namespace std;
template <typename e>
class mc
{
typedef struct node
{
e a,b;
}node;
node p;
public:
void print();
};
template <typename e>
void mc<e>::print()
{
std::cout<<p.h;
}
int main()
{
mc<int> m;
//m.print();
return(0);
}
The compiler shows an error only when m.print() is uncommented in main. Why is that?
If you donot use the object (instance) of a template, compiler only check the logic of the template. The template will not be instantiated. But if you try to use a instance of a template, that template will be instantiated (expanded) then you will see the error that h is not a member of p.
That is to say that , if you comment out //m.print(), the template will be instantiated.
In order to make writing template classes a bit easier, non-invoked template methods are not instantiated.
A few things are checked -- the signature of the method, and it does lookup of any methods or functions that involve only data non-dependent on the template parameters of the class and the like.
In this case, p is technically dependent on the template parameters of the class, so the check that p.h is valid is done at instantiation. Now, you could prove that there is no e such that p.h is valid, but the compiler doesn't have to, so it doesn't bother.
The program may still be ill-formed: there are clauses in the standard where programs can be ill-formed (no diagnostic required) if there are no valid specializations of a template, but I do not know if that applies to a method of a template or not.
Once you invoke print, the method is instantiated, and the error is noticed.
An example of where this is used in the std library is vector -- a number of its methods, including <, blinding invoke < on its data. vector does not require that its data support <, but it does require it if anyone tries to call <.
Modern C++ techniques would involve disabling vector::operator< in that case (the standard talks about "does not participate in overload resolution"), and in C++1z this becomes far easier via requires clauses (if that proposal ever gets standardized).
I have a container object that is templatized. I am trying to make a specialized constructor for float versions. Problem is, when the compiler attempts to compile the second object that uses the float version, I get a multiple definition of error.
NOTES: The entire class in in the h file. The file is wrapped with a definition (#ifndef, #define, and #endif). g++ version 3.4.6. This compiles fine with other compilers, e.g. Intel's icc.
Code is similar to the following:
template <typename T>
class Container {
public:
Container();
virtual ~Container() {}
private:
std::vector<T> data;
// other members
};
template <> Container<float>::Container() {
// do something special
}
template <typename T> Container<T>::Container() {
// do default initialization
}
Any ideas? Thanks!
EDIT The objects being compiled are also going into separate shared objects, not sure if that has something to do with it.
Specializations still must abide by the one-definition rule just like any other non-template method. Either mark it inline or define the method body in a source file (not your header).
template <> Container<float>::Container() {
// do something special
}
is a definition of the specialisation. A specialisation has to be declared in every compilation unit it is used:
template <> Container<float>::Container();
and defined in only one of the CU. So your .h has to have the declaration and you have to find an adequate (probably new) .cpp for the definition. (As Mark B point out, making the specialization inline is also a way to allow to put the definition in all compilation unit where it is needed).
This is tricky. The problem is that your specialization is not a
template, but an actual function definition. And since it's in a
header, you get multiple definitions when you include it twice.
Something like:
template<> Container<float>::Container();
in the header, and the implementation in a single source file.
you could use typeid:
template <typename T> Container<T>::Container() {
if(typeid(T)==typeid(float)) {
// do something special
}
else {
// do default initialization
}
}
downside: you cant use initialization list for your special case.
EDIT:
When i wrote this answer, i still assumed that the error was caused by the compiler, not by the code of the OP (did not look into it that much). However this typeid approach is absolutely valid C++ (see link below), and its a quite nice workaround if templates indeed would not work correctly with your specific compiler, and it can easily be replaced by the template solution if once day you can switch to a better compiler.
demonstration: example # ideone
I heard C++ templates wont generate errors until they are used. Is it true ? Can someone explain me how they work ?
Templates follow two phase compilation model.
struct X{
private:
void f(){}
};
template<class T> void f(T t){
int; // gives error in phase 1 (even if f(x) call is commented in main)
t.f(); // gives error only when instantiated with T = X, as x.f() is private, in phase 2
}
int main(){
X x;
f(x);
}
They generate compiler errors when they are compiled. They are compiled separately for each actual parameter passed as the template argument(s) (this is unlike Java Generics), e.g., if I have:
template <typename T> class foo { ... }
and
int main() {
foo<char> c;
foo<int> i ;
}
the template foo gets compiled twice, once for chars, once for ints.
If you never (directly or indirectly) instantiated or used template foo, it wouldn't be compiled and you'd not see any compiler errors.
Once compiled, they're just "normal" C++ code, and like any code, can generate runtime errors.
From here,
From the point of view of the
compiler, templates are not normal
functions or classes. They are
compiled on demand, meaning that the
code of a template function is not
compiled until an instantiation with
specific template arguments is
required. At that moment, when an
instantiation is required, the
compiler generates a function
specifically for those arguments from
the template.
Hope it helps..
Conceptually, at the highest level
template <Type value, class Y, ...>
...fn-or-class...
may be usefully compared to
#define FN_OR_CLASS(VALUE, TYPE_Y, ...) \
...fn-or-class...
Both basically wait until called/instantiated then substitute the specified types and values to produce tailored code with full compile-time optimisation for those values. But, templates differ from #defines in that they're proper compile-stage constructs that can be enclosed in namespaces, must satisfy the lexer, and not all of a class template is generated when the first instantiation is seen - rather, functions are generated on an as-needed basis.
When the compiler first encounters a template, it does a rough check that the template's content could make sense for some hypothetical instantiation. Later, when it encounters a specific instantiation, then for class templates only the functions that are used are further checked to make sure they can be compiled with the specific parameters in use. This does mean that a class template can appear - for some limited usage - to support instantiation with specific parameters, but if you start using some other functions in the template API then suddenly you can find that it can't be compiled with that presumed-suitable parameter... can force you to redesign your usage rather late in the day. That is one of the reasons that C++0x had planned to introduce Concepts: they elegantly allow templates to check that parameters meet all the template's expectations - if they allow any instantiation, then the user can assume that the full API of the template can be used.
template <class T>
struct X
{
void f() { }
void g() { T::whatever(); } // only error if g() called w/o T::whatever
};
int main()
{
X<int> x;
x.f();
// x.g(); // would cause an error as int::whatever() doesn't exist...
}
The SFINAE (substitution failure is not an error) technique can then allow the compiler to select between multiple nearly-matching functions based on the actual instantiating template parameters. This can be used to implement basic compile-time introspection, such as "does this class have a member function fn(int)?".
Always considering that the following header, containing my templated class, is included in at least two .CPP files, this code compiles correctly:
template <class T>
class TClass
{
public:
void doSomething(std::vector<T> * v);
};
template <class T>
void TClass<T>::doSomething(std::vector<T> * v) {
// Do something with a vector of a generic T
}
template <>
inline void TClass<int>::doSomething(std::vector<int> * v) {
// Do something with a vector of int's
}
But note the inline in the specialization method. It is required to avoid a linker error (in VS2008 is LNK2005) due to the method being defined more then once. I understand this because AFAIK a full template specialization is the same as a simple method definition.
So, how do I remove that inline? The code should not be duplicated in every use of it. I've searched Google, read some questions here in SO and tried many of the suggested solutions but none successfully built (at least not in VS 2008).
Thanks!
As with simple functions you can use declaration and implementation.
Put in your header declaration:
template <>
void TClass<int>::doSomething(std::vector<int> * v);
and put implementation into one of your cpp-files:
template <>
void TClass<int>::doSomething(std::vector<int> * v) {
// Do somtehing with a vector of int's
}
Don't forget to remove inline (I forgot and thought this solution will not work :) ).
Checked on VC++2005
You need to move specialization definition to CPP file.
Specialization of member function of template class is allowed even if function is not declared as template.
There is no reason to remove the keyword inline.
It does not change the meaning of the code in anyway.
If you want to remove the inline for whatever reason the solution of maxim1000 is perfectly valid.
In your comment, though, it seems you believe that the inline keyword means that the function with all his contents gets always inlined but AFAIK that is actually very much dependent on your compiler optimization.
Quoting from the C++ FAQ
There are several ways to designate that a function is inline, some of
which involve the inline keyword, others do not. No matter how you
designate a function as inline, it is a request that the compiler is
allowed to ignore: the compiler might inline-expand some, all, or none
of the places where you call a function designated as inline. (Don’t
get discouraged if that seems hopelessly vague. The flexibility of the
above is actually a huge advantage: it lets the compiler treat large
functions differently from small ones, plus it lets the compiler
generate code that is easy to debug if you select the right compiler
options.)
So, unless you know that that function will actually bloat your executable or unless you want to remove it from the template definition header for other reasons, you can actually leave it where it is without any harm
This is a little OT, but I thought I'd leave this here in case it helps someone else. I was googling about template specialization which led me here, and while #maxim1000's answer is correct and ultimately helped me figure my problems out, I didn't think it was abundantly clear.
My situation is a little different (but similar enough to leave this answer I think) than the OP's. Basically, I'm using a third party library with all different kinds of classes that define "status types". The heart of these types are simply enums, but the classes all inherit from a common (abstract) parent and provide different utility functions, such as operator overloading and a static toString(enum type) function. Each status enum is different from one another and unrelated. For example, one enum has the fields NORMAL, DEGRADED, INOPERABLE, another has AVAILBLE, PENDING, MISSING, etc. My software is in charge of managing different types of statuses for different components. It came about that I wanted to utilize the toString functions for these enum classes, but since they're abstract I couldn't instantiate them directly. I could have extended each class I wanted to use, but ultimately I decided to create a template class, where the typename would be whatever concrete status enum I cared about. Probably some debate can be had about that decision, but I felt like that was a lot less work than extending each abstract enum class with a custom one of my own and implementing the abstract functions. And of course in my code, I just wanted to be able to call .toString(enum type) and have it print the string representation of that enum. Since all the enums were entirely unrelated, they each had their own toString functions that (after some research I learned) had to be called using template specialization. That led me here. Below is an MCVE of what I had to do in order to make this work correctly. And actually my solution was a bit different than #maxim1000's.
This is a (greatly simplified) header file for the enums. In reality, each enum class was defined in it's own file. This file represents the header files that are supplied to me as part of the library I am using:
// file enums.h
#include <string>
class Enum1
{
public:
enum EnumerationItem
{
BEARS1,
BEARS2,
BEARS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
class Enum2
{
public:
enum EnumerationItem
{
TIGERS1,
TIGERS2,
TIGERS3
};
static std::string toString(EnumerationItem e)
{
// code for converting e to its string representation,
// omitted for brevity
}
};
adding this line just to separate the next file into a different code block:
// file TemplateExample.h
#include <string>
template <typename T>
class TemplateExample
{
public:
TemplateExample(T t);
virtual ~TemplateExample();
// this is the function I was most concerned about. Unlike #maxim1000's
// answer where (s)he declared it outside the class with full template
// parameters, I was able to keep mine declared in the class just like
// this
std::string toString();
private:
T type_;
};
template <typename T>
TemplateExample<T>::TemplateExample(T t)
: type_(t)
{
}
template <typename T>
TemplateExample<T>::~TemplateExample()
{
}
next file
// file TemplateExample.cpp
#include <string>
#include "enums.h"
#include "TemplateExample.h"
// for each enum type, I specify a different toString method, and the
// correct one gets called when I call it on that type.
template <>
std::string TemplateExample<Enum1::EnumerationItem>::toString()
{
return Enum1::toString(type_);
}
template <>
std::string TemplateExample<Enum2::EnumerationItem>::toString()
{
return Enum2::toString(type_);
}
next file
// and finally, main.cpp
#include <iostream>
#include "TemplateExample.h"
#include "enums.h"
int main()
{
TemplateExample<Enum1::EnumerationItem> t1(Enum1::EnumerationItem::BEARS1);
TemplateExample<Enum2::EnumerationItem> t2(Enum2::EnumerationItem::TIGERS3);
std::cout << t1.toString() << std::endl;
std::cout << t2.toString() << std::endl;
return 0;
}
and this outputs:
BEARS1
TIGERS3
No clue if this is the ideal solution to solve my problem, but it worked for me. Now, no matter how many enumeration types I end up using, all I have to do is add a few lines for the toString method in the .cpp file, and I can use the libraries already-defined toString method without implementing it myself and without extending each enum class I want to use.
I'd like to add that there is still a good reason to keep the inline keyword there if you intend to leave also the specialization in the header file.
"Intuitively, when you fully specialize something, it doesn't depend on a template parameter any more -- so unless you make the specialization inline, you need to put it in a .cpp file instead of a .h or you end up violating the one definition rule..."
Reference: https://stackoverflow.com/a/4445772/1294184
Currently I have a frustrating problem with forward declaration and template function. I have been trying to googling and do some modification but nothing has worked so far. Below is the snippet of the code:
class TaskScheduler; --> //forward declaration of ‘struct TaskScheduler’
//
//
class TaskEvent {
//
//
};
class HostTask {
//
//
};
template<class T> inline HostTask*
findT(TaskScheduler* tss, T* e)
{
map<int, HostTask*>::iterator it;
bool bEq = false;
for(it = tss->tasks_.begin(); it != tss->tasks_.end(); it++) { --> //error: invalid use of incomplete type ‘struct TaskScheduler’
if(dynamic_cast<TaskEvent*>(e))
bEq = dynamic_cast<TaskEvent*>(e)->equal(it->second->ev_);
else if(dynamic_cast<HostTask*>(e))
bEq = dynamic_cast<HostTask*>(e)->equal(it->second);
if(bEq) {
return it->second;
}
}
return NULL;
}
//
//class TaskScheduler definition
class TaskScheduler : virtual public HCIEventsHandler {
friend HostTask* findT<TaskEvent>(TaskScheduler* tss, TaskEvent* e); //findT function is used here
//
//
};
Here is the error message that I've got which is shown in the code as well:
./bt-taskscheduler.h:159: error: forward declaration of ‘struct TaskScheduler’
./bt-taskscheduler.h:229: error: invalid use of incomplete type ‘struct TaskScheduler’
Could anybody show me what is going wrong in this code? Any help is appreciated..
In the definition of findT you are using tss->tasks_ which dereferences a pointer to an object of type TaskScheduler so you need a full definition of the struct, not just a forward declaration visible at this point in the program.
The definition of struct TaskScheduler needs to appear before the definition of the findT function template.
You are using the TaskScheduler class in your for-loop header "tss->tasks_.begin()". Compiler does not know, whether this class have "tasks_" member or not.
It is not the problem with your templates, any function, inlined in the header file will cause the same error. Forward declaration of the class only allows you to declare pointers (or references) to that class or pass this class objects as a parameters. You cannot "use" the class (call its methods or get the member data), until you fully define your class.
Because you use the definition of TaskScheduler in the findT functions, you have two options:
Move the definition of TaskScheduler above the findT template function
Make TaskScheduler a second template of of the findT function
Like this:
template< class U, class T>
inline HostTask* findT( U* tss, T* e)
{
//...
}
Next to trouble with the forward declaration, it looks as if your findT function should actually be a member function of the scheduler class: it makes extensive use of the scheduler's data members.
These members are private, so you need a way to publish them, and fall back onto the friend declaration.
So either you make the members public, or, better, you refactor the findT function into a member function.
There's no problem in making it a templated member function, either. And you will automatically get rid of the friend declaration.
//class TaskScheduler definition
class TaskScheduler : virtual public HCIEventsHandler {
public:
template<class T> inline HostTask* findT(T* e) const
{
map<int, HostTask*>::iterator it;
bool bEq = false;
for(it = tasks_.begin(); it != tasks_.end(); it++) {
if(dynamic_cast<TaskEvent*>(e))
bEq = dynamic_cast<TaskEvent*>(e)->equal(it->second->ev_);
else if(dynamic_cast<HostTask*>(e))
bEq = dynamic_cast<HostTask*>(e)->equal(it->second);
if(bEq) {
return it->second;
}
}
return NULL;
}
};
As other posters have mentioned, you are dereferencing a pointer to TaskScheduler without a definition of the type, which will cause an error just as it would in any definition.
What you are probably confused about is that your code likely works on some compilers, even modern ones (I know MSVC is incorrect in this regard, but I do not know if it will accept the above code*). These compilers do not properly implement what is known as two-phase name lookup.
Two-phase name loopkup is a more predictable method of name lookup used in templates than the simpler form used by some compilers. In the simpler form, the template definition is parsed and stored for use only when it's instantiated, and name lookup is performed on all names in the template from the point at which you instantiate the template. With two-phase name lookup, names used within a template are sorted into dependent names and non-dependent names. Non-dependent names are names that the compiler can resolve immediately - any name that doesn't rely on a template parameter, directly or indirectly. These names are processed immediately when you define the template. Dependent names, on the other hand, cannot be resolved immediately; they are stored and then, when instantiation is performed, looked up in the template's context, but also in the context in which the template was instantiated for argument-dependent lookup only.
Here's an example:
void foo (int);
template <typename T> void bar(T t) {
foo(1.0);
foo(t);
}
void foo (double);
struct qux {};
void foo (qux);
void baz () {
bar (1.0);
qux q;
bar (q);
}
N.B. I know I got the metasyntactic names in the wrong order. I apologize, but I added qux last and couldn't be bothered to rewrite my comment.
The instantiations of the bar template each call foo twice. The first call is non-dependent, so the compiler resolves it as soon as it sees it. The result is that it calls foo (int), applying a conversion, even though it will later find a better definition. This is no different from any other function call in C++. The tricky bit comes with the second call, which is dependent. The first call in baz calls bar<double>, the latter calls bar<qux>. The instantiated bar attempts to call foo with an object of type T. In the double scenario, since primitives never use argument-depedent lookup, the result is once again looked up only from bar, and foo(int) is found. When called with qux, however, argument-dependent lookup is applied both in the the definition and instantiation context**, so foo(qux) is called.
It can be a tad stupid, but it tends to Do The Right Thing. Also, I hope you actually understood that; it can be rather confusing. You'll need to read that Wikipedia link to understand fully.
* MSVC may implement a lesser form of two-phase name lookup where it does resolve non-dependent names correctly, but it takes into account definitions after the template for dependent names. I forget whether it does this or omits two-phase lookup entirely and I don't have a copy of the program to check.
** In nearly every case, the instantiation context includes every declaration the definition context does. There is, however, the export keyword which can cause this not to be the case. That keyword is only implemented in one compiler frontend - I wonder why nobody else has implemented it? [/sarcasm]