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
{};
Related
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.
Is it possible to derive all template instantiations that have a derived class as their argument from the instantiation that has the base class as its argument?
In code:
class Base{};
class Derived1 : Base{};
class Derived2 : Base{};
template<typename T>
class Templ /*: Templ<Base> if T derives from Base*/
{};
How would one do that?
Make a specialization for Templ<Base>, and then use SFINAE along with std::is_base_of to derive a separate specialization from Templ<Base>.
template<typename T, typename V = void>
class Templ
{};
template<>
class Templ<Base>
{};
template<bool B, typename R = void>
using enable_if_t = typename std::enable_if<B, R>::type;
template<typename T>
class Templ<T, enable_if_t<std::is_base_of<Base, T>::value>>
: public Templ<Base>
{};
It depends what exactly you want to do. If you want this to work only for some specific, known baseclass, it can easily accomplished, e.g. like in 0x499602D2's answer.
However the way I interpret your question you want to have a template which derives from the instantiation for it's arguments baseclass, whichever that might be. This is not possible in standard c++ (yet), since there is no way to query what class a specific type is derived from, only if it is derived from a specific classes. For more on this (and possible future solutions look at this question.
Is there anyway to specialize a trait template for a nested class? I've tried it in the three places noted below, each with the given error. I've seen questions regarding specializing nested template classes, but that's not what I'm trying to do here-- I'm trying to specialize a trait class that is used by the nested class.
The TraitUser class makes use of the definitions within the Trait as specialized to a specific type T. Perhaps most relevantly, it uses a trait member to initialize a base class.
template<T>
class TraitUser:public X<typename Trait<T>::Type>
{
//Trait<T> gets used in here
};
//class A;
//class A::B; <-incomplete type used in nested name
//template<>
//struct Trait<A::B>
//{};
class A
{
private:
//class B;
//template<> <-explicit specialization at class scope
//struct Trait<B>
//{};
class B:TraitUser<B>
{};
};
//template<> <- specialization after instantiation
//struct Trait<A::B>
//{};
It looks like the root of the trouble is not being able to forward declare a nested class and also not being able to define a specialization inside a class declaration.
I'm trying this under clang using C++11.
There's some complicated declaration ordering here:
template <class T>
struct Trait;
template <class T>
struct X
{};
template<class T>
class TraitUser:public X<typename Trait<T>::Type>
{
//Trait<T> gets used in here
};
class A
{
private:
class B;
};
template<>
struct Trait<A::B>
{
typedef int Type;
};
class A::B : public TraitUser<B>
{};
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.
When having:
template <typename Super>
class Whatever : public Super
{
...
};
is it possible, to create Whatever class without deriving from something?
Is this the lighter version?
struct BlankType{};
Whatever<BlankType> w;
////////////////////////////////////////
Some background:
I have my code composed into template layers like Whatever above. So I can do:
typedef Whatever<Whenever<Wherever<>>>> MyCombinedType
actually I can not. I have to do
typedef Whatever<Whenever<Wherever<BlankType>>>> MyCombinedType
and the type becomes also BlankType.
I can not make Wherever "non-layerable", because when I would do just
typedef Whatever<Whenever<>>> MyCombinedType
the problem will appear again...
If you want to create Whatever class that is not derived from something you can simply define its specification as follows:
class BlankType {};
template<typename T = BlankType> class Whatever : public T {};
template<> class Whatever<BlankType> {};
A bit off-topic, in C++ with variadic templates you can avoid the recursive instantiation thanks to a recursive definition:
template <class ...Bases> class Whatever;
template <class B, class ...Bases>
class Whatever<B, Bases...> : public B, public Whatever<Bases...> { /* ... */ };
template <class B>
class Whatever<B> : public B { /*... */ };
template <> class Whatever<> { /* ... */ };
Now you can say Whatever<Foo, Bar, Baz> and inherit from all those. If you want to inherit also from multiply nested other instances of Whatever, you should make all the inheritances virtual.
The final specialization in my example also shows how you can specialize Whatever to not derive from anything. If you write Whatever<> x;, you have an object of a class that does not derive from anything.