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
Related
Consider something like this in C#:
class C<T> {}
class D : C<E> {}
class E : C<D> {}
Is an equivalent construction possible in C++ using templates?
Yes, you can forward declare E:
template <typename T> class C {};
class E;
class D : public C<E> {};
class E : public C<D> {};
or, as per Franks suggestion:
template <typename T> class C {};
class D : public C<class E> {};
class E : public C<D> {};
Whether this works in your real case depends on whether C requires T to be complete (it does not in this stripped down example).
PS: I don't know C#, so I am not sure if you wanted private or public inheritance. The above uses public inheritance, while the default for classes declared with the keyword class is private inheritance.
I have a non-template parent interface and am trying to use SFINAE on a child class. All I want to do is verify the type of the first template parameter can be constructed without any arguments. My issue is in forward declaration. Based on my understanding, SFINAE requires a class to be forward declared and then specialized. This is currently what I'm trying:
class ParentInterface
{};
template<class, class = void>
class Child : public ParentInterface; // <-- This semi-colon is the error
template<class Ty>
class Child<Ty, std::enable_if_t<std::is_constructible_v<Ty>>>
: public ParentInterface
{};
The answers I was able to find related to this had to do with inheriting from a SFINAE class. What do I need to do to get my intended functionality?
template<class, class = void>
class Child : public ParentInterface;
is neither a declaration nor definition.
You probably want declaration:
`template<class, class = void>
class Child;
And then you can add your partial specialization definition:
template<class Ty>
class Child<Ty, std::enable_if_t<std::is_constructible_v<Ty>>>
: public ParentInterface
{};
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.
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.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Is there a way to prevent a class from being derived from twice using a static assert and type trait?
What I'd like to prevent is more than one of the C based template from being derived in D (i.e. there should only ever be one instance of C derived from). Was hoping for maybe a static assert in C or B that may solve this.
// My Classes
template <class T>
class A {};
class B {};
template <class T, class S>
class C : public B, public virtual A<T> {};
// Someone elses code using my classes
class D : public C<Type1, Type2>, public C<Type3, Type4>
{
};
As it stands, it's impossible for B or C to detect what else a more derived class inherits from, so you can't add an assertion there. However, by adding a "curiously recursive" template parameter, you can tell C what the derived class is. Unfortunately, this does require the derived class to give the correct template argument, and there's no way to enforce that.
You can then determine whether the derived class inherits from B in more than one way; it is a base class, but you can't convert a derived class pointer to B* (since that conversion is ambiguous). Note that this doesn't necessarily indicate multiple inheritance; the test will also fail if there's non-public inheritance.
So the best solution I can think of is:
#include <type_traits>
template <class T> class A {};
class B {};
template <class T, class S, class D>
class C : public B, public virtual A<T> {
public:
C() {
static_assert(
std::is_base_of<C,D>::value && std::is_convertible<D*,B*>::value,
"Multiple inheritance of C");
}
};
struct Type1 {};
struct Type2 {};
struct Type3 {};
struct Type4 {};
class Good : public C<Type1, Type2, Good> {};
class Evil : public C<Type1, Type2, Evil>, public C<Type3, Type4, Evil> {};
int main()
{
Good good;
Evil evil; // Causes assertion failure
}
I had to put the assertion in the constructor rather than the class definition, since some of the types are incomplete when the class template is instantiated. Unfortunately, this means that the error will only be reported for classes that are actually instantiated.