template alias in specialized class - c++

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.

Related

template parameter name as base class

I've the following types:
typedef unsigned int uint32;
typedef void* ptr;
struct memory_options {};
struct memory_provider {};
template <typename options>
struct memory_track {};
template <typename options>
struct no_memory_track : public memory_track<options> {};
template<typename options>
struct defrag_memory_track : public memory_track<options> {};
template<typename options>
struct full_memory_track : public memory_track<options> {};
template <typename options, typename prov, typename track>
struct memory_algorithm : public track < options > {};
int main()
{
}
This types used to define a custom memory manager.
The problem is the class memory_algorithm will inherit from another class, that class will always take a template parameter that represent memory_options class, i call it options. The base class may be a partial specialization from memory_track or a subclass from it, so in memory_algorithm i passed 2 template parameters one represents the class name - i.e. track - and the other represent the memory_options class - i.e. options - now whenever i tried to compile the code with sample test unit using GCC and Visual C++ 2008 i got the error:
for visual c++:
missing ',' before '<'
see reference to class template instantiation 'memory_algorithm' being compiled
for GCC:
error: expected template-name before '<' token
error: expected '{' before '<' token
error: expected unqualified-id before '<' token
What is the problem and how to fix it?
If I understand your question correctly, what you need is probably to make track a template template parameter, rather than a regular type parameter:
template <typename options, typename prov, template<typename> class track>
// ^^^^^^^^^^^^^^^^^^^^^^^^
struct memory_algorithm : public track < options > {};

C++ templates cross definition

I want to know if is it possible in C++ to do that :
template <typename T> class A { T link;};
template <typename U> class B { U link;};
class AA : A<BB> {};
class BB : B<AA> {};
because it generates the error :
error: ‘BB’ was not declared in this scope
error: template argument 1 is invalid
i have tryed to use anticipate declaration :
class AA;
class BB;
class AA : A<BB> {};
class BB : B<AA> {};
but it didn't work :
In instantiation of ‘A<AA>’:
error: ‘A<T>::s’ has incomplete type
error: forward declaration of ‘struct AA’
thank you for your help,
Your problem isn’t the templates, it’s the infinite nesting (and yes, technically from using incomplete types to define members). Remove the templates and you’ll get the same issue:
struct A;
struct B;
struct A { B x; };
struct B { A y; };
Conceptually, this can’t work. Because, really, what you’d get here is an A that contains a B that contains an A that contains a B … to infinity. Turtles all the way down.
What does work, however, is using pointer members instead. Those work with incomplete types, and consequently the code works – and even with templates.
template <typename T> class A { T* link;};
template <typename U> class B { U* link;};
Check out this question I asked some time back. How to forward declare a template class
Basically, if you are forward declaring a template type, you have to specify all the template parameters.

C++ templates and structs problem

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?

Nested struct type in a template class

template <typename vec1, typename vec2>
class fakevector
{
public:
/* Do something */
};
template <class A>
class caller
{
public:
struct typeList
{
struct typeOne
{
//...
};
};
typedef fakevector<typeList::typeOne,int> __methodList; /* This will trigger compile error */
};
The error messages I got are:
Error: type/value mismatch at
argument 1 in template parameter
list for ‘template class fakevector’
Error: expected a type, got ‘caller::typeList::typeOne’
If template is removed from the caller class, no error will be reported,
like this
class caller
{
public:
struct typeList
{ ....
};
I don't know the reason. Thank you very much!
Try:
typedef fakevector<typename typeList::typeOne,int> __methodList;
http://www.comeaucomputing.com/techtalk/templates/#typename
Looks like the compiler is in doubt what typeOne is.
typedef fakevector<typename typeList::typeOne,int>
should compile
Try typedef fakevector<typename typeList::typeOne,int>
The typename prefix to a name is required when the name
Appears in a template
Is qualified
Is not used as in a list of base class specifications or in a list of member initializers introducing a constructor definition
Is dependent on a template parameter
Furthermore, the typename prefix is not allowed unless at least the first three previous conditions hold.

Mapping integers to types using C++ template fails in a specific case

I am attempting to compile the following template based code in VC++ 2005.
#include <iostream>
using namespace std;
/*
* T is a template which maps an integer to a specific type.
* The mapping happens through partial template specialization.
* In the following T<1> is mapped to char, T<2> is mapped to long
* and T<3> is mapped to float using partial template specializations
*/
template <int x>
struct T
{
public:
};
template<>
struct T<1>
{
public:
typedef char xType;
};
template<>
struct T<2>
{
public:
typedef long xType;
};
template<>
struct T<3>
{
public:
typedef float xType;
};
// We can easily access the specific xType for a specific T<N>
typedef T<3>::xType x3Type;
/*!
* In the following we are attempting to use T<N> inside another
* template class T2<R>
*/
template<int r>
struct T2
{
//We can map T<r> to some other type T3
typedef T<r> T3;
// The following line fails
typedef T3::xType xType;
};
int main()
{
T<1>::xType a1;
cout << typeid(a1).name() << endl;
T<2>::xType a2;
cout << typeid(a2).name() << endl;
T<3>::xType a3;
cout << typeid(a3).name() << endl;
return 0;
}
There is a particular line in the code which doesn't compile:
typedef T3::xType xType;
If I remove this line, compilation goes fine and the result is:
char
long
float
If I retain this line, compilation errors are observed.
main.cpp(53) : warning C4346: 'T<x>::xType' : dependent name is not a type
prefix with 'typename' to indicate a type
main.cpp(54) : see reference to class template instantiation 'T2<r>' being compiled
main.cpp(53) : error C2146: syntax error : missing ';' before identifier 'xType'
main.cpp(53) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
I am not able to figure out how to make sure that T::xType can be treated as a type inside the T2 template. Any help is highly appreciated.
Since T3 in your template class depends on the template parameter, the compiler can't known for sure what T3::xType will refer to (that might depend on the actual type r in each instantiation T2<r>).
To tell the compiler that T3::xType will be a type, you need to add the typename keyword:
typedef typename T3::xType xType;
Try
typedef typename T3::xType xType;
The error message tells you exactly what you need to do: Add typename before the type.
typedef typename T3::xType xType;
The reason you need this is that if there's an identifier that can be treated as a variable or a type, the compiler will treat it as a variable, which is what's happening in this case. In order to let the compiler know that it's actually a type you use the typename keyword.