Simple concept check - c++

Say I have a simple template like this:
template<typename T>
class A {};
And I want to specify that the type-parameter T is of some unrelated type X<U> where U is not known (or unspecifyable).
Is there a way how to express that as a concept?

Is there a way how to express that as a concept?
You don't need a concept, class template specialization works just fine in your case.
As an example, you can do this:
template<typename T>
class A;
template<typename U>
class A<X<U>> { /* ... */ };
This way, unless A is instantiated with a type of the form X<U> (where U is unknown), you'll get a compile-time error because the primary template isn't defined. In other terms, it won't work for all the types but X<U> (for each U), where the latter matches the class template specialization that has a proper definition.
Note that I assumed X is a known type. That's not clear from your question.
Anyway, if it's not and you want to accept types of the form X<U> for each X and each U, you can still do this:
template<typename T>
class A;
template<template<typename> class X, typename U>
class A<X<U>> { /* ... */ };
As a minimal, working example:
template<typename>
struct S {};
template<typename>
class A;
template<typename U>
class A<S<U>> {};
int main() {
A<S<int>> aSInt;
A<S<double>> aSDouble;
// A<char> aChar;
}
Both A<S<int>> and A<S<double>> are fine and the example compiles. If you toggle the comment, it won't compile anymore for A<char> isn't defined at all.
As a side note, if you don't want to use class template specialization and you want to simulate concepts (remember that they are not part of the standard yet and they won't be at least until 2020), you can do something like this:
#include<type_traits>
template<typename>
struct X {};
template<typename>
struct is_xu: std::false_type {};
template<typename U>
struct is_xu<X<U>>: std::true_type {};
template<typename T>
struct A {
static_assert(is_xu<T>::value, "!");
// ...
};
int main() {
A<X<int>> aXInt;
A<X<double>> aXDouble;
// A<char> aChar;
}
That is, given a generic type T, static assert its actual type by means of another structure (is_xu in the example) that verifies if T is of the form X<U> (for each U) or not.
My two cents: the class template specialization is easier to read and understand at a glance.

template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };
Now given a class template:
template <typename T>
struct X {};
a type template parameter can be constrained using:
template <typename T> requires Template<T, X>
class A {};
or:
template <Template<X> T>
class A {};
DEMO
This will work also for types derived from X<U>.

Related

Avoiding template parameter substitution completely

I have a class that can accept arithmetic types and std::complex. A simplified code of the class is
#include <complex>
template<typename T> struct is_complex : std::false_type {};
template<typename T> struct is_complex<std::complex<T>> : std::true_type {};
template<class T>
struct Foo {
void foo(typename T::value_type t)
requires (is_complex<T>::value) {
}
};
Now, I would like to take the internal type of std::complex and use it as the type of the parameters in the foo function.For example, if T is std::complex<double>, then I want the parameter types to be double.
This function should only be available when T is indeed std::complex.
I thought I could use typename T::value_type as the parameter type, since std::complex has a typedef value_type. Plus, I thought using requires here would avoid T to be substitued in this function in case T wasn't std::complex. Silly me.
The issue is that whenever I create a Foo<FundamentalType> the code breaks, since fundamentals don't have ::value_type.
int main() {
Foo<int> obj; // Breaks the code.
//obj.foo(4); // Function shouldn't be considered in overload resolution ideally...
Foo<std::complex<int>> obj2; // Works
obj2.foo(4); // Works as expected
}
Ideally, I would like the substitution of T to be ignored for this function in case T is not std::complex. Is that possible? If not, how can I circumvent this?
You're on the right track with is_complex: you'd like the same here, but with a different body of the type. For example,
template<typename T> struct complex_value_type {};
template<typename T> struct complex_value_type<std::complex<T>> { using type = T; };
template<typename T>
using complex_value_type_t = typename complex_value_type<T>::type;
Then, at any point, you can call it as complex_value_type_t<T>:
template<class T>
struct Foo {
template<typename T_ = T>
void foo(complex_value_type_t<T_> t)
requires (is_complex<T_>::value) {
}
};
The requires is not absolutely necessary then; it's already covered by complex_value_type_t<T> being defined only for complex<T>.
You just need some type to put in there, until requires can disable the function.
I would do this:
struct nullptr_value_type {using value_type = std::nullptr_t;};
using elem_or_null_t = typename std::conditional_t<is_complex<T>::value, T, nullptr_value_type>::value_type;
void foo(elem_or_null_t t)
requires (is_complex<T>::value)
{}
Use a template class as a template parameter.
#include <complex>
template<template<class> class T> struct is_complex : std::false_type {};
template<> struct is_complex<std::complex> : std::true_type {};
template<template<class> class T>
struct Foo {
void foo(typename T<double>::value_type t)//could be typename<T<TT>> if you made foo a templated function
requires (is_complex<T>::value) {
}
};
int main(){
Foo<std::complex> f;
};
But you will need what to put into it when used. I just hard-coded double but you have to add a new template parameter to Foo or make foo a templated member function

Is it possible to infer second template argument type for this template class?

I have a template class A
template<template<class> class E, class N>
class A
{}
and I also have a template function that takes A as an argument:
template<class T>
auto make_something(const T& t){}
used like make_something(a) on an object a of A type.
I would like to be able to tell what is the type N from inside the make_something function. Is there any way of achieving this without changing the template argument of make_something?
(In the following I've changed template<class> class E to template<class, class> class E because I used std::vector, which has two type template parameters, for E.)
I have no idea what you're doing, but to ask question about types, you need to write some traits.
I guess something like the following could be a starting point:
// to ask if something is an A at all
template<typename T>
struct IsAnA : std::false_type {};
template<template<class, class> class E, class N>
struct IsAnA<A<E, N>> : std::true_type {};
template<typename T>
constexpr bool is_an_A_v = IsAnA<T>::value;
// to query A's second template arg
template<typename T>
struct SecondTemplArgOfA {};
template<template<class, class> class E, class N>
struct SecondTemplArgOfA<A<E, N>> {
using type = N;
};
template<typename T>
using second_templ_arg_of_A_t = typename SecondTemplArgOfA<T>::type;
// make use of it
template<class T>
auto make_something(const T& t){
if constexpr (is_an_A_v<T>) {
using its2ndTemplArg = second_templ_arg_of_A_t<T>;
// so what?
} else {
// you've fed make_something with a non-A, so
// you can't get its second template arg
}
}
Demo.

How to specialize class template based on boolean metafunction?

I have a primary template, which I need to specialize based on based on a meta-function. The usual idiom is like
template<class T,class E = void>
struct foo { };
template<class T>
struct foo<T,std::enable_if_t<is_xxx<T>{}> > {};
However, I have a situation where the primary template is written as
template<class T>
struct foo { };
(i.e. without that extra SFINAE placeholder) and I am not allowed to change it. What is the best way to specialize it based on a trait( like I can do that mostly for function template based on return type or additional argument)?
You can add a base class:
template<class T, class E = void>
struct foo_base { };
template<class T>
struct foo : foo_base<T, std::enable_if_t<is_xxx<T>{}>> { };
Then you move any members of foo into foo_base.

Applying partially applied template

Having a class like the A, is there a way to apply it to a template like this of B, with T2 set to some type C? But without creating another template class inheriting from A.
template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
With C++11 using a template alias works:
template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
class C
{ };
template< typename T > using A1 = A< T, C >;
int main()
{
B< A1 > b;
}
without C++11, you are left with what you probably already know:
template< typename T > class A1 : A< T, C > {};
I will propose an alternative solution: do not use template template parameters.
If you write:
template <typename T> struct B {};
Then it can be used with A<int, int> or C<3> or even plain D.
Whilst it is possible to use template template parameters, it is general a bad idea. You should treat the template parameter of a class as an implementation detail and apply the golden rule: do not rely on implementation details.
If you need access to the type, somehow, then use an associated type (aka T::AssociatedType) or a trait (BTraits<T>::AssociatedType).
EDIT: dealing with multiple instantiations of the template template parameter.
Suppose we want to "erase" the template template parameter of such a class:
template <template <typename> class A>
struct Something {
template <typename T>
void doit() { A<T>::doit(); }
};
The C++ standard allocation model is to use an inner rebind structure:
template <typename T>
struct Simple {
template <typename U>
struct rebind { typedef Simple<U> type; };
};
template <typename T0, typename T1>
struct Multi {
template <typename U>
struct rebind { typedef Multi<U, T1> type; };
};
template <typename A>
struct Something {
template <typename T>
void doit() { typedef typename A::rebind<T>::type B; B::doit(); }
};
Note how you can use complex computations in rebind and nothing forces you in blindly passing the type received as parameter.
Whilst another (similar) solution is to ask for a factory (aka, the object passed itself cannot be used but it can build useful objects); for ease of use the C++ containers ask of their allocators that they be both usable in themselves and factories for other types.
Yes, you can do it using C++11's alias template:
template <typename T>
using AA = A<T, C>;
B<AA> b;
Live example

Partial template binding, create new template as type

Is there some way to partially bind a template to parameter types? For example, I have the following template:
template<typename T, typename Q> struct generic { };
And I have another template which takes a template class as a parameter, expecting to be able to create instances of it with the first type:
template<typename T, template<typename> class Impl>
struct wrapper {
Impl<T> foo;
};
This would accept a simple template like template<typename T> without changes. What I want to do now is partially bind the generic template, specifying only Q and passing it to wrapper. Making up some syntax, perhaps something like this:
template<typename T> bound = generic<T,some_type>;
I know I can almost get what I want using inheritance:
template<typename T> bound : public generic<T,some_type> { };
I am hoping though to avoid this though as it causes issues with constructors and operators defined in the base class.
In C++11 you can use template aliases
template<class X>
using Bind_CPP11 = generic<X, Y>;
template<class X, template<class> class Impl>
struct wrapper_CPP11
{
Impl<X> foo;
};
In C++98/03, you can use simple class composition (I would not use inheritance here)
template<class X>
struct Bind_CPP03
{
typedef generic<X, Y> type;
};
template<class X, template<class> class Impl>
struct wrapper_CPP03
{
typename Impl<X>::type foo;
// ^^^^^^^^ to extract dependent type
};
Live Example.