template parameter name as base class - c++

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

Related

Compiler error when using an inner class template in instantiating a class template

GCC 7.5.0 is giving me an error message that I'm puzzled about. This is the smallest piece of code I can come with that generates the message:
template<template<typename> typename>
struct A
{
};
template<char>
struct X
{
template<typename>
struct Y
{
};
};
template<char c>
struct B : public A<X<c>::Y>
{
};
GCC 7.5.0 says:
../main.cpp:18:28: error: type/value mismatch at argument 1 in template parameter list for ‘template<template<class> class<template-parameter-1-1> > struct A’
subdir.mk:18: recipe for target 'main.o' failed
struct B : public A<X<c>::Y>
^
../main.cpp:18:28: note: expected a class template, got ‘X<c>::Y’
Is the problem perhaps that the argument to A in the inheritance clause must be a class template that sits at namespace level? This is not the case with X::Y. Unfortunately, I do not know how to do without putting Y inside of X. Application-specific stuff not shown seems to mandate it.
You need to tell the compiler that X<c>::Y is a template and not a type or variable. Try the following:
template<char c>
struct B : public A<X<c>::template Y>
{
};
Demo here
For a rather longer discussion of exactly when you need to specify this kind of thing and why, this question is very thorough.

Variadic template template and SFINAE

I'm toying with SFINAE and I try to check my Inputs is made of Input of various types. The error provided by clang doesn't help much. Do you have any idea ?
Thanks
struct IsFree
{
};
template <typename _Type, typename _State>
struct Input
{
};
template <typename... _Inputs>
struct Inputs
{
};
template <template <typename _Type, typename _State> class, typename... _Inputs>
struct Inputs<Input<_Type, _State>, _Inputs...> : public Inputs<_Inputs...>
{
};
Somewhere else :
auto temp = Inputs<Input<float, IsFree>, Input<float, IsFree>> {};
I get using clang-5.0 and -std=c++17 :
13 : <source>:13:21: error: use of undeclared identifier '_Type'
struct Inputs<Input<_Type, _State>, _Inputs...> : public Inputs<_Inputs...>
^
13 : <source>:13:35: error: expected a type
struct Inputs<Input<_Type, _State>, _Inputs...> : public Inputs<_Inputs...>
^
2 errors generated.
Compiler exited with result code 1
template <template <typename _Type, typename _State> class, typename... _Inputs>
struct Inputs<Input<_Type, _State>, _Inputs...> : public Inputs<_Inputs...>
{
};
needs to be
template <typename _Type, typename _State, typename... _Inputs>
struct Inputs<Input<_Type, _State>, _Inputs...> : public Inputs<_Inputs...>
{
};
in the pattern Input<_Type, _State> _Type and _State are just type wildcards, you only need the template <typename, typename> class F template template parameter syntax if you need to match a template template parameter with a wild card. In this case you are matching the template with a known template named Input
Your partial specialization for the last case is not correct. You need to deduce _Type and _State, not have a template template parameter.
template <class _Type, class _State, typename... _Inputs>
struct Inputs<Input<_Type, _State>, _Inputs...> : public Inputs<_Inputs...>
{
};
In your original code, the names inside the template template parameter do not introduce template parameters for that partial specialization.
Also note that names beginning with an underscore and capital letter are reserved to the implementation, so you should not use them in your own code.
Other than the perfect answers already provided by others, may I ask what your expected outcome is of a type like Inputs<Input<float, IsFree>, int, Input<int, IsFree>>? Notice the stray int in the middle. Would you like the base class recursion to stop at the first non-Input<> argument, as currently is the case in your example, or rather have a compile error?
If the latter, might I suggest changing the general Inputs template definition to be an incomplete type, and then specializing for an empty struct in case of zero template arguments, like so:
// General case, incomplete type
template<class... T>
struct Inputs;
// Special case for zero arguments, empty struct
template<>
struct Inputs<>
{
};
Together with your specialization for Inputs<Input<*,*>, ...>, this will make sure you can never instantiate a template using arguments that are not a list of Input<*,*>.

template alias in specialized class

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.

C++ nested class as template argument for parent

I am trying to create a derived class that is using a nested class as a template argument for a parent class, but the compiler is unable to instanciate the template:
template<typename T>
class A {};
template<typename T>
class B : public A<typename B<T>::nested_class >
{
class nested_class : public std::pair<std::string, T>
{
// adds methods that use the T type
};
};
MSVC 2010 gives me 3 errors trying to compile this:
syntax error : missing ',' before identifier 'nested_class'
'nested_class' : undeclared identifier
'A' : use of class template requires template argument list
Moving the nested class out and making it separate solves the problem, but I want to understand why this doesn't compile.

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.