Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple concept check

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?

like image 733
wimalopaan Avatar asked Mar 06 '17 07:03

wimalopaan


People also ask

What is a concept check?

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.

What are examples of concept questions?

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 main purpose of a concept checking question?

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.


2 Answers

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.

like image 106
skypjack Avatar answered Oct 21 '22 21:10

skypjack


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>.

like image 21
Piotr Skotnicki Avatar answered Oct 21 '22 23:10

Piotr Skotnicki