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?
Concept checking is checking the understanding of difficult aspects of the target structure in terms of function and meaning. Concept checking is vital, since learners must fully understand the structure before any intensive practice of form and phonology is carried out.
Concept questions should check the understanding of the language item, not of the situation. For example, when checking understanding of mustn't: “You mustn't walk on the grass”. Why mustn't I walk on the grass?
What is the main purpose of a concept checking question? In a word, understanding. In the physical or online classroom, the main purpose of a CCQ in TEFL/TESOL is to determine if the student understands what you've taught without explicitly asking, “Hey, student, do you understand now!?” Imagine the awkwardness.
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>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With