0

I have a class which needs two separate templates passed into it:

template <typename T> class AwesomeClass { TList *theList; typename list <T>::iterator theiterator; public: template <typename TList> AwesomeClass(TList &list) { theList = &list; }; } 

As you can probably tell it essentially provides a wrapper for the STL (I have to do it this way). Ideally I do not want to pass both templates through at object declaration like this:

typedef AwesomeClass<int, BaseClass<int> > BaseClassIteratorInt; 

and would rather get away with this:

typedef BaseClass<int> ListFromBaseClassInt; typedef AwesomeClass<int> BaseClassIteratorInt; BaseClassIteratorInt newInt(ListFromBaseClassInt) 

(This is what the above code is meant to do)

However, I keep getting the error:

error C2143: syntax error : missing ';' before '*'

For the variable TList* theList.

I would need the to ctor to provide the type for TList, is there a way to do this?

Extra steps:

Okay, I now have code of the format:

template <typename Container> class AwesomeClass { public: typedef typename std::common_type< Container > value_type; bool firstUse; Container *theList; typename Container::iterator theIterator; explicit AwesomeClass(Container &list):theList(&list) { }; } 

This is using common_type to get around a compiler bug which stop the line

typedef typename Container::value_type value_type; 

compiling due to value_type not being a part of the global namespace.

But I have a compiler error for theIterator, the compiler claims that it needs a ';' before it.

Can anyone see what is wrong?

4
  • ListIterator is the actual name, I generally try to change the class names etc. when I post on forums and missed one! Commented Feb 28, 2014 at 10:54
  • I can understand that if the names are proprietary. But please be consistent. Not to mention the fact that in this case, the original name is well-chosen as it self-documents what the class does. Why make it harder for us to understand code you want us to help you with? Commented Feb 28, 2014 at 10:55
  • Just so I got this straight - you class stores a pointer to an arbitrary list type, and and iterator into std::list<T>? You might want to explain your purpose better, as this doesn't make much sense at first sight. Commented Feb 28, 2014 at 10:56
  • In the edit you probably meant typedef typename std::common_type<Container>::type::value_type value_type;. Otherwise value_type will be e.g. std::common_type<std::list<int>> instead of int. Commented Feb 28, 2014 at 12:19

4 Answers 4

1

I don't think you need two template params for that.

template <class Container> class AwesomeClass { public: // you can use this typedef to access the value type typedef typename Container::value_type value_type; AwesomeClass(Container &list): theList(&list) {} private: Container *theList; typename Container::iterator theiterator; }; int main() { // you can use typedef if you like typedef std::list<int> intList; intList list{1, 2, 3}; AwesomeClass<intList> newInt(list); } 
Sign up to request clarification or add additional context in comments.

7 Comments

While this may very well be what the OP wants, it's equivalent to the code they posted - it's storing an iterator into TList, the original code has std::list<T>::iterator. Still, +1 from me - I believe you managed to grasp the actual intent.
This looks perfect but I seem to be getting a compilation error for the value_type. It is 'not a member of the global namespace', apparently this is a compiler bug. I have tried using a workaround (added to my question) but I get an error at the declaration of theIterator - the compile complains that there should be a ';' before it?
@Stefan, that's odd. Your new class compiles fine in gcc(ideone) if you add the missing semicolon after your class definition. But the warning from that shouldn't point to theIterator line.
Yeah, it is a bug with MSVC 2010 compiler
value_type and iterator both have type std::common_type<Container>. You must use the member type type and nested typdef's to get to the value respective iterator types. E.g. typedef typename std::common_type<Container>::type::value_type value_type.
|
0

it sound like you need a forward declaration for TList: you are using if before declaring it so the compiler can't know about it.

1 Comment

If I add a forward declaration for TList I seem to get an error when it is first used claiming that the type is undefined?
0

With

template <typename T, typename TList> class AwesomeClass class AwesomeClass { TList *theList; typename list<T>::iterator theiterator; public: explicit AwesomeClass(TList &list) : theList(&list) {} }; 

What you can do to deduce type at construction is a free function:

template<typename T, typename TList> AwesomeClass<T, TList> make_AwesomeClass(TList& tlist) { return AwesomeClass<T, TList>(tlist); } 

Call it that way:

auto awesomeClass = make_AwesomeClass<int>(mylist); 

3 Comments

Template argument deduction of T will fail for function make_AwesomeClass.
@Snps: it is true that T cannot be deduced, but you want to deduce TList from mylist (And I assumed that T and TList are unrelated which seems wrong after your edit).
Though I'm not the OP ;)
0

You need to declare TList as a template parameter before you can use it in other declarations.

template <typename TList, typename T> class AwesomeClass { TList* theList; /* ... */ }; 

Also you don't need to declare the second template parameter T, instead get the type like so:

using value_type = typename TList::value_type; 

Secondly, you don't have to use template deduction in the ctor.

// template <typename TList> // Unnecessary if the template parameter is already declared AwesomeClass(TList& list) { theList = &list; } 

Thirdly, you have put the semicolon after the ctor instead of at the end of the class scope.

/* ... */ AwesomeClass(TList& list) { theList = &list; }; // Unnecessary to put semicolon after function definitions. } // Although, you need semicolon here. 

It looks like you want to be able to automatically deduce the types of the template parameters when creating an object of AwesomeClass. However, class template parameters can not automatically be deduced, only function templates can do that.

To accomplish automatic deduction of template parameters you can create a function that returns a AwesomeClass with the deduced parameters, e.g.

template <typename TList> auto make_awesome(TList& list) -> AwesomeClass<TList, typename TList::value_type> { return {list}; } 

Edit:

If what you want is a class that stores a pointer to a std::list of any type then all you need to deduce is the element type. But then you can only store a pointer to a std::list container, not e.g. a pointer to std::vector.

template <typename T> class AwesomeClass { public: AwesomeClass(std::list<T>& c) { c_ = &c; } private: std::list<T>* c_; typename std::list<T>::iterator iter_; }; int main() { typedef AwesomeClass<int> BaseClassIteratorInt; BaseClassIteratorInt b{l}; } 

3 Comments

But if I add TList as template parameter like you have shown I get an error when attempting to use the declaration: typedef AwesomeClass<int> BaseClassIteratorInt; as there are too few parameters. Having a semi colon at the end of a function declaration does not really make any difference although I have removed it as it was not intentional!
@Stefan If the class requires two template parameters, then you must supply two parameters. Try this: typedef AwesomeClass<std::list<int>, int> BaseClassIteratorInt;
That works but it is already what I have now. The libraries I am replacing only use one parameter in the typedef to declare their classes. If possible I would like to interface to be identical.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.