C++ nested class as template argument for parent - c++

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.

Related

CRTP and template template parameters limitation

I'm trying to experiment with CRTP but I am puzzled on why the following code does not compile.
template<template<class...> class CBase>
struct ComponentX : public CBase<ComponentX>
{
// This does NOT compile
};
template<template<class...> class CBase>
struct ComponentY : public CBase<int>
{
// This does compile
};
Do you know if there is some limitation for template template parameters in the case of CRTP?
A class template name stands for the "current specialization" (i.e. it is an injected class name) only after the opening { of the class template definition, inside its scope. Before that, it's a template name.
So CBase<ComponentX> is an attempt to pass a template as an argument to CBase, which expects a pack of types.
The fix is fairly simple:
template<template<class...> class CBase>
struct ComponentX : public CBase<ComponentX<CBase>> // Specify the arguments
{
// This should compile now
};
ComponentX<CBase> is the name of the specialization you wish to provide as a type argument.

Inherit base constructor with base class being a template parameter (MSVC)

I try to achieve this code using VS2017, and get errors :
template <class T>
class A {
public :
A() {}
};
template < template <class U> class T, class U>
class B : public T<U> {
using T<U>::T;//Errors : # 'T': is not a member of 'A<U>' # 'T': symbol cannot be used in a using-declaration
};
int main() {
B<A, int> test;
return 0;
}
Works perfectly using Clang and GCC according to https://wandbox.org/
I'd like to know why it's not working on Visual Studio, and how to fix it. Looks like VS doesn't want to consider second 'T' parameter as a template.
Here is another question previously asked the closest I could find about this matter. Couldn't find a solution reading it though :
Inheriting constructors from a template base class
The workaround is to define a typedef alias
typedef T<U> base_t;
and use it to inherit the constructors from the base class:
using base_t::base_t;
This is not a unique compiler bug; I dimly recall a similar issue with an old version of gcc.

How can a template class inherit from a nested template class

Consider the following code :
template<class C, class P>
//class Cchild : public C::NestedClass // Works
class Cchild : public C::NestedTemplateClass<P> // Fails : how to inherit from nested template class defined in C ?
{
};
Compiler compiles fine when template class Cchild inherits from a nested class C::NestedClass . However, it fails to compile if I want Cchild to inherit from a nested template class C::NestedTemplateClass<P>
How can I do this ?
The syntax is:
template<class C, class P>
class Cchild : public C::template NestedTemplateClass<P>
{
};
The error message from gcc was actually quite readable:
t.C:3:26: error: non-template ‘NestedTemplateClass’ used as template
class Cchild : public C::NestedTemplateClass<P>
^~~~~~~~~~~~~~~~~~~
t.C:3:26: note: use ‘C::template NestedTemplateClass’ to indicate that it is a template

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

How to forward declare the following template class

I try to forward declare concurrent_bounded_queue ;
class MyClass {
namespace tbb {
template<typename T> class cache_aligned_allocator;
template<class T, class A = cache_aligned_allocator> class concurrent_bounded_queue;
};
// I wish to maintain this syntax.
tbb::concurrent_bounded_queue<std::string>& concurrentBoundedQueue;
}
I get the following error :
error C3203: 'cache_aligned_allocator' : unspecialized class template can't be used as a template argument for template parameter 'A', expected a real type
error C2955: 'tbb::cache_aligned_allocator' : use of class template requires template argument list c:\projects\vitroxreport\src\Executor.h(21) : see declaration of 'tbb::cache_aligned_allocator'
May I know how I can avoid?
Thanks.
Allocator is a template, but second argument of the queue is concrete class. Try this:
class MyClass {
namespace tbb {
template<typename T> class cache_aligned_allocator;
template<class T, class A = cache_aligned_allocator<T> >
class concurrent_bounded_queue;
};
tbb::concurrent_bounded_queue<std::string>& concurrentBoundedQueue;
};