Comprobación de concepto simple


Digamos que tengo una plantilla simple como esta:

template<typename T>
class A {};

Y quiero especificar que el parámetro de tipo T es de algún tipo no relacionado X<U> donde U no se conoce (o no se puede especificar).

¿Hay alguna manera de expresar eso como un concepto?

Author: Rakete1111, 2017-03-06

2 answers

¿Hay alguna manera de expresar eso como un concepto?

No necesitas un concepto, la especialización de plantillas de clase funciona bien en tu caso.
Como ejemplo, puedes hacer esto:

template<typename T>
class A;

template<typename U>
class A<X<U>> { /* ... */ };

De esta manera, a menos que A se instancie con un tipo de la forma X<U> (donde U es desconocido), obtendrá un error en tiempo de compilación porque la plantilla primaria no está definida. En otros términos, no funcionará para todos los tipos, pero X<U> (para cada U), donde este último coincide con la especialización de plantilla de clase que tiene una definición adecuada.

Tenga en cuenta que asumí X es un tipo conocido. Eso no está claro en tu pregunta.
De todos modos, si no lo es y desea aceptar tipos de la forma X<U> para cada X y cada U, todavía puede hacer esto:

template<typename T>
class A;

template<template<typename> class X, typename U>
class A<X<U>> { /* ... */ };

Como un ejemplo mínimo:

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;
}

Tanto A<S<int>> como A<S<double>> están bien y el ejemplo compila. Si cambia el comentario, ya no se compilará para A<char> isn't definido en absoluto.


Como nota al margen, si no quieres usar la especialización de plantillas de clase y quieres simular conceptos (recuerda que aún no forman parte del estándar y no lo serán al menos hasta 2020), puedes hacer algo como esto:

#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;
}

Es decir, dado un tipo genérico T, estática afirmar su tipo real por medio de otra estructura (is_xu en el ejemplo) que verifica si T es de la forma X<U> (para cada U) o ni.


Mis dos centavos: la especialización de plantillas de clase es más fácil de leer y entender de un vistazo.

 30
Author: skypjack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-06 09:04:32
template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };

Ahora se le da una plantilla de clase:

template <typename T>
struct X {};

Un parámetro de plantilla de tipo se puede restringir usando:

template <typename T> requires Template<T, X>
class A {};

O:

template <Template<X> T>
class A {};

DEMO

Esto también funcionará para los tipos derivados de X<U>.

 11
Author: Piotr Skotnicki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-06 10:41:46