I would like to specialize default_delete<_Ty> for all objects derived off of MyBaseClass. This was my best attempt:
template <typename T>
struct default_delete<typename enable_if<is_base_of<MyBaseClass, T>::value, T>::true_type>
{
...
};
The compiler seems to be unable to recognize that my type parameter 'T' is being used, which is understandable given that it is 'downstream' from a 'typename' keyword. Is what I'm trying to accomplish possible?
As 0x499602D2 states in comment, it is not possible without an extra dedicated template parameter. you may use your own deleter as follow:
template <typename T, typename Enable = void>
struct my_default_delete : public std::default_delete<T> {}; // default to std::default_delete<T>
template <typename T>
struct my_default_delete<T, typename std::enable_if<std::is_base_of<MyBaseClass, T>::value>::type>
{
void operator() (T* ) { /* Your specific implementation */ }
};
Related
Consider the following class structure:
template <typename TType>
struct Base {public: virtual ~Base() {} };
template <typename TType>
struct Child : Base<TType> {};
template <template<typename> class Node, typename TType>
bool type(Node <TType>* node){
return dynamic_cast<Base<TType>*>(node) == nullptr;
}
int main(){
Child<int> child;
type(&child);
}
This code works fine, as long as the child has the same template type before and after casting. If this is not the case, it will of course fail. If they have different types and I provide the specific type of the inherited template, it will work, but I have a very big number of possible templates. My first instinct was to add another template:
template <template<typename TType> class Node, typename TType, typename TType2>
bool type(Node <TType>* node){
return dynamic_cast<Base<TType2>*>(node) == nullptr;
}
This will give an error "couldn't deduce template parameter", because the compiler does not know which type it is, as no corresponding parameter is passed (but I am not able to provide this in beforehand).
Is there any solution to this? I am also open to other possibilites than dynamic_cast, as my actual goal is, if the templated node is a subclass of the also templated baseclass.
I tried e.g. is_base_of without success. Something around the lines of is_base_of<Base, typeid(child)>::value did not work because of a type msimatch in the arguments.
You might use overload:
template <typename T>
constexpr std::true_type IsBaseT(const Base<T>*) { return {}; }
constexpr std::false_type IsBaseT(const void*) { return {}; }
Demo
That assumes accessible, non ambiguous base. And result is based on static type.
So you can turn that into a traits:
template <typename T>
std::true_type IsBaseTImpl(const Base<T>*); // No impl
std::false_type IsBaseTImpl(const void*); // No impl
template <typename T>
using IsBaseT = decltype(IsBaseTImpl(std::declval<T*>()));
And a more generic form:
template <template <typname> C, typename T>
std::true_type IsCTImpl(const C<T>*); // No impl
template <template <typname> C>
std::false_type IsCTImpl(const void*); // No impl
template <template <typname> C, typename T>
using IsCT = decltype(IsCTImpl<C>(std::declval<T*>()));
template <typename T>
using IsBaseT = IsCT<Base, T>;
With concepts, C++20 provides nice syntax like
template<typename T>
concept SomeConcept = true; // stuff here
template<typename T>
requires SomeConcept<T>
class Foo;
template<SomeConcept T>
class Foo;
where the two ways of concept restricting the class are equivalent, but the latter is just more concise.
If i now have some template template concept like
template<template<typename> typename T>
concept SomeOtherConcept = true; // stuff here
template<template<typename> typename T>
requires SomeOtherConcept<T>
class Foo;
i do not know the non-verbose (concise / short) syntax for this without an requirement clause, as things like
template<template<typename> SomeotherConcept T>
class Foo;
template<template<SomeOtherConcept> typename T>
class Foo;
did not work, so
What is the correct syntax for declaring such a template template class with a concept restriction to the template template parameter?
What is the correct syntax for declaring such a template template class with a concept restriction to the template template parameter?
The only way to write a constraint that depends on a template template parameter or a non-type template parameter is with a requires-clause. The shorter type-constraint syntax is only available for concepts that constrain types (hence the name type-constraint):
template <typename T> concept Type = true;
template <template <typename...> class Z> concept Template = true;
template <auto V> concept Value = true;
// requires-clause always works
template <typename T> requires Type<T> struct A { };
template <template <typename...> class Z> requires Template<Z> struct B { };
template <auto V> requires Value<V> struct C { };
// type-constraint only for type concepts
template <Type T> struct D { };
// abbreviated function template definitely only for type concepts
void e(Type auto x);
This is a trick that I have used before.
Define a lambda in the primary expression using a noop-like function as shown:
void noop(auto) {}
//...
template<typename T>
concept SomeConcept = true;
/*
template <template<typename>SomeConcept T>
struct Example {};
*/ //does not work
template <template<typename>typename T>
requires requires() {
{
noop(
[]<typename TArg> requires SomeConcept<typename T<TArg>> (){}
)
};
}
struct Example {};
I'm learning templates and concepts. I'm trying to make a concept for types that are derived from a class, but this class is a template.
template<typename T>
struct CAA{};
template<typename T, typename T2>
concept DerivedFromAA = requires() {std::derived_from<CAA<T2>,T>;};
Is it possible to use such concept in a function without having to explicitly tell it the template type of the class? Is my idea wrong on how to define such concept?
template<typename T>
void conceptTestFunc(DerivedFromAA<T> auto& aa)
{
}
//...
CAA<int> aa;
conceptTestFunc<int>(aa); // Without having to tell it "int"
(I'm compiling this with Clang.)
A template is not a type.
So if CAA is a template, then CAA<int> would be a type.
A type can't be derived from a template, only from another type. This means that the check has to be done on the type, not the template.
If you on the other hand want to deduce the inner type of aa, that can be done.
#include <concepts>
template<typename T>
struct CAA{};
template<typename T>
struct CBB{};
template<typename T, typename T2>
concept DerivedFromAA = std::derived_from<CAA<T2>,T>;
template<template <typename> typename Outer, typename T>
requires DerivedFromAA<Outer<T>, T>
void conceptTestFunc(Outer<T>& aa)
{
}
int main() {
CAA<int> aa;
conceptTestFunc(aa);
CBB<int> bb;
conceptTestFunc(bb); // This fails
}
You might do
template<typename T>
concept DerivedFromAA = requires(T t) {[]<typename U>(CAA<U>&){}(t);};
static_assert(DerivedFromAA<CAA<int>>);
Demo
gcc dislikes lambda in requires, so you might create dummy helper function outside.
I am trying to understand type function in template metaprogramming trough some examples.
I have created one example that removes the reference from a type.
template <class T>
struct remove_reference
{ using type = T; };
template <class T>
struct remove_reference<T&>
{ using type = T; };
int main(){
typename remove_reference<int&>::type a;
}
My question is if this is implemented using partial template specialization of if we call it something else?
I feel it is partial because we have not defined it for a specific type but I also feel it isn't because we have just as many template arguments.
The naming may not be important to understanding type functions but I don't want to teach other people the wrong names if I explain it.
Yes, it is partial specialisation, because you have restricted to just things that match the pattern T&.
You don't need to have fewer template parameters, you can even have more. E.g.
template <typename Callable>
struct function_something { ... }; // Any functor type
template <typename Ret, typename Args...>
struct function_something<Ret(Args...)> { ... }; // Specialises free functions
template <typename Class, typename Ret, typename Args...>
struct function_something<Ret(Class::*)(Args...)> { ... }; // Specialises member functions
I asked this question earlier where a solution was presented. The solution is great as far as the question is concerned, but now I am confused on how I would define the methods outside of the class i.e. I would like to define the methods in an .inl file. What would be the syntax in this case?
Just to be clear, for a template class, the method definition will be:
template <typename T>
struct Foo
{
Foo();
};
// C-tor definition
template <typename T>
Foo<T>::Foo()
{
}
How would I define methods for the template class with enable_if as one of the parameters?
template <typename Policy, enable_if< is_base<BasePolicy, Policy>::value >::type >
struct Foo
{
Foo();
};
// C-tor definition -- ???
From the looks of it, you want to do something along the lines of this:
template <typename Policy,
typename = typename std::enable_if<std::is_base_of<BasePolicy, Policy>::value>::type >
struct Foo;
template <typename Policy>
struct Foo<Policy> {
Foo();
};
template <typename Policy>
Foo<Policy>::Foo() {
}
This sneakily takes advantage of the default argument in a few places: don't get confused, there is an implicit void sitting in several locations.
Here's how SFINAE can actually work with partial specialization:
template<typename T, typename Sfinae = void>
struct Foo {
/* catch-all primary template */
/* or e.g. leave undefined if you don't need it */
};
template<typename T>
struct Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type> {
/* matches types derived from BasePolicy */
Foo();
};
The definition for that constructor can then be awkwardly introduced with:
template<typename T>
Foo<T, typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type>::Foo()
{
/* Phew, we're there */
}
If your compiler supports template aliases (it's a C++11 feature) that then you can cut a lot of the verbosity:
template<typename T>
using EnableIfPolicy = typename std::enable_if<std::is_base_of<BasePolicy, T>::value>::type;
// Somewhat nicer:
template<typename T>
struct Foo<T, EnableIfPolicy<T>> {
Foo();
};
template<typename T>
Foo<T, EnableIfPolicy<T>>::Foo() {}
Note: your original answer referred to utilies from Boost, like boost::enable_if_c and boost::is_base_of. If you're using that instead of std::enable_if and std::is_base_of (which are from C++11), then usage looks like
typename boost::enable_if<boost::is_case_of<BasePolicy, T> >::type
which has the advantage of getting rid of one ::value.