I am working through some C++ code from "Financial Instrument Pricing Using C++" - a book on option pricing using C++. Following code is a small snippet stripped of many details which basically attempts to define a SimplePropertySet class that is intended to contain a name and list.
#include <iostream>
#include <list>
using namespace::std;
template <class N, class V> class SimplePropertySet
{
private:
N name; // The name of the set
list<V> sl;
public:
typedef typename list<V>::iterator iterator;
typedef typename list<V>::const_iterator const_iterator;
SimplePropertySet(); // Default constructor
virtual ~SimplePropertySet(); // Destructor
iterator Begin(); // Return iterator at begin of composite
const_iterator Begin() const;// Return const iterator at begin of composite
};
template <class N, class V>
SimplePropertySet<N,V>::SimplePropertySet()
{ //Default Constructor
}
template <class N, class V>
SimplePropertySet<N,V>::~SimplePropertySet()
{ // Destructor
}
// Iterator functions
template <class N, class V>
SimplePropertySet<N,V>::iterator SimplePropertySet<N,V>::Begin()//<--this line gives error
{ // Return iterator at begin of composite
return sl.begin();
}
int main(){
return(0);//Just a dummy line to see if the code would compile
}
On compiling this code on VS2008, I obtain the following errors:
warning C4346: 'SimplePropertySet::iterator' : dependent name is not a type
prefix with 'typename' to indicate a type
error C2143: syntax error : missing ';' before 'SimplePropertySet::Begin'
error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
Is there something stupid or basic that I am getting wrong or forgetting here? Is it a syntax error? I am unable to put my finger on it. The book from which this code snippet is taken says their code was compiled on Visual Studio 6. Is this some version-related issue?
Thanks.
As indicated by the compiler, you must replace :
template <class N, class V>
SimplePropertySet<N,V>::iterator SimplePropertySet<N,V>::Begin()
with :
template <class N, class V>
typename SimplePropertySet<N,V>::iterator SimplePropertySet<N,V>::Begin()
See this link for an explanation on dependent names.
Related
The following code gives the error (in line where i define test):
error C2143: syntax error: missing ';' before '<'
note: see reference to class template instantiation 'ptc::Produce' being compiled
error C4430: missing type specifier - int assumed.
Note: C++ does not support default-int
Does anybody know why this happens?
Compiler is VC2015 CTP1.
Edit: the error must happen in phase1 of the template parsing, because it occurs even I never instantiate the class Produce.
namespace OrderPolicy
{
struct Unordered {};
struct Ordered {};
};
template <typename TOrderPolicy>
struct OrderManager {};
template<>
struct OrderManager<OrderPolicy::Unordered>
{
template <typename TItem>
using item_t = TItem;
};
template<>
struct OrderManager<OrderPolicy::Ordered>
{
template <typename TItem>
using item_t = TItem*;
};
template<typename TOrderPolicy>
struct Produce : public OrderManager<TOrderPolicy>
{
item_t<int> test;
//using item_type = item_t<int>;
};
Edit2: it works when I change the last part of the code to
struct Produce : public OrderManager<OrderPolicy::Ordered>
{
item_t<int> test;
//using item_type = item_t<int>;
};
item_t<int> test;
That names a dependent template type from a base class. In this case, you need to tell the compiler both that item_t is a type in your base class, and that it's a template.
The direct way to do this is using typename and template:
typename OrderManager<TOrderPolicy>::template item_t<int> test;
As you can see, this will quickly become unreadable. I would make some local aliases to make the code neater:
using Base = OrderManager<TOrderPolicy>;
using item_type = typename Base::template item_t<int>;
item_type test;
You'll have to use:
typename OrderManager<TOrderPolicy>::template item_t<int>
in place of:
item_t<int> test;
wow, learning never stops. Until now I did not see the keyword template used in this context.
Please see the updated code after the break;
I have the following templated class:
template<class T> class CDFAManListOps
{
static std::list<T>::iterator CDFAManListOps::GetIterator(std::list<T>* list, int pId)
{
}
}
When I try to compile it, it says
std::list<T>::iterator' : dependent name is not a type 1> prefix with 'typename' to indicate a type.
But if I change the function like the compiler asks me to:
static typename std::list<T>::iterator CDFAManListOps::GetIterator(std::list<T>* list, int pId)
the compiler (VS12) crashes with the following error:
fatal error C1001: An internal error has occurred in the compiler.
1> (compiler file 'msc1.cpp', line 1443)
1> To work around this problem, try simplifying or changing the program near the locations listed above.
Any idea what's wrong with this code?
UPDATE: This is the entirety of the smallest amount of code that I could get that reproduces this crash.
#include <list>
template<class T> class CDFAManListOps
{
static typename std::list<T>::iterator CDFAManListOps::GetIterator(std::list<T>* list, int pId)
{
}
static typename std::list<T>::iterator CDFAManListOps::GetIterator(std::list<T>* list, T object)
{
}
};
int main()
{
}
If I take out EITHER of the two GetIterator functions, the program compiles and runs fine. Only when BOTH functions are present will the compiler crash. Does this make it any clearer what the problem in my code is?
(Also, I will be filing a bug report with Microsoft Connect and posting the link here if anyone wants to keep up with its status.)
I have filed a bug report on Microsoft Connect here.
UPDATE: Microsoft has decided not to do anything about this particular bug in the foreseeable future. See the Microsoft Connect link above.
I can't reproduce your problem with the given code in MSVS2012.
This compiles fine:
#include <list>
template<class T>
class CDFAManListOps
{
public:
static typename std::list<T>::iterator GetIterator(std::list<T>* list, size_t pId)
{
typename std::list<T>::iterator it = list->begin();
for (size_t i=0; i<pId; ++i) ++it;
return it;
}
};
int main(void)
{
std::list<size_t> x(5);
CDFAManListOps<size_t>::GetIterator(&x, 2);
return 0;
}
Ok, I can reproduce the problem now. Removing CDFAManListOps:: from your in-class definition will result in correct compilation of your code.
#include <list>
template<class T> class CDFAManListOps
{
static typename std::list<T>::iterator GetIterator(std::list<T>* list, int pId) {}
static typename std::list<T>::iterator GetIterator(std::list<T>* list, T object) {}
};
int main() {}
As a workaround, try typedefing the iterator type as a class member before the function declaration:
template<class T> class CDFAManListOps
{
typedef typename std::list<T>::iterator iter_t;
static iter_t GetIterator(std::list<T>* list, int pId)
{
}
};
or fully specify the list type:
template<class T> class CDFAManListOps
{
template <typename Allocator>
static typename std::list<T, Allocator>::iterator GetIterator(std::list<T, Allocator>* list, int pId)
{
}
};
Why do I keep on getting the following error in this code in Visual C++ 2010, and how do I fix it while maintaining the type inference capability for the member variable?
error C2825: 'Foo<T>::value_type': must be a class or namespace when followed by '::'
template<class T>
struct Foo
{
typedef typename T::value_type value_type;
template<class M>
void foo(M value_type::*member) const; // error
};
struct S { typedef int value_type; };
int main() { Foo<S> s; }
The template parameter T turns out to be type S, therefore value_type turns out to be int (the nested-type in S). So how can you write value_type::*member? Note that it turns out to be int::*member which doesn't make sense. int is not a class type.
I think you meant T::*member instead of value_type::*member.
value_type is not a member of structure S.
Its just a typedef so you cant access it as you are doing.
I have
template <typename ConcContainer>
class WebBrowsingPolicyData
{
public:
typedef ConcContainer<std::shared_ptr<WBRuleDetails>>::iterator iterator;
...
private:
ConcContainer<std::shared_ptr<WBRuleDetails>> usersData_;
CRITICAL_SECTION critSection
I get a compile error at line (Error 6 error C2238: unexpected token(s) preceding ';')
typedef ConcContainer<std::shared_ptr<WBRuleDetails>>::iterator iterator
How can I make a typedef inside the template ? I must be missing something..
ConContainer is itself a template so it needs to be a template template parameter:
template <template <typename T> class ConcContainer>
class WebBrowsingPolicyData
{
public:
typedef typename ConcContainer<std::shared_ptr<WBRuleDetails>>::iterator iterator;
};
Two possibilities:
The compiler is having trouble with >>. Insert a space. Note that if you're using a C++11-conformant compiler, this should not be an issue.
example:
typedef ConcContainer<std::shared_ptr<WBRuleDetails> >::iterator iterator;
ConcContainer doesn't have a member or typedef iterator. Check to make sure that it really does.
EDIT: This is not the most vexing parse.
I have this...
template <typename Key, typename Value>
class A {
public:
//...
private:
struct MyStruct{
Key key;
Value value;
};
};
And it gives me the following errors:
Error 1 error C2146: syntax error : missing ';' before identifier 'value'
Error 2 error C4430: missing type specifier - int assumed.
Error 3 error C4430: missing type specifier - int assumed.
Some specs:
Using Visual Studio 2010
Windows 7 x64
Can my error be before or after these lines?
You forgot a semicolon after the class definition, at the very end of your code.
In some cases you need to write typename Key key; instead of a simple Key key; in templates, since the compiler may not know that Key is really a typename. So try this:
template <typename Key, typename Value>
class A {
public:
//...
private:
struct MyStruct {
/* typename not allowed here */ Key key;
/* typename not allowed here */ Value value;
};
};
You forgot the last semi-colon to end your class definition.
It looks like you missed a semi-colon to close out your class.
This compiles fine for me using g++ 4.6.1:
#include <iostream>
template <typename Key, typename Value>
class A {
public:
A() {}
private:
struct MyStruct {
Key key;
Value value;
};
};
int main(void) {
A<int, char> a;
}
First, maybe it's just a typo in the code you pasted, but you are missing the ; at the end of the class definition.
Beyond that, I don't see a problem. Make sure you are declaring an object as
A<type, type> a;
What are you using for your template types?