web-dev-qa-db-ja.com

シンプルなコンセプトチェック

次のような単純なテンプレートがあるとします。

template<typename T>
class A {};

そして、タイプパラメータTが無関係なタイプX<U>であり、Uが不明(または指定不能)であることを指定したいと思います。

それをコンセプトとして表現する方法はありますか?

24
wimalopaan

それをコンセプトとして表現する方法はありますか?

概念は必要ありません。クラステンプレートの特殊化は、あなたのケースでは問題なく機能します。
例として、次のことができます。

template<typename T>
class A;

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

このように、AX<U>形式のタイプ(Uは不明)でインスタンス化されない限り、プライマリテンプレートが定義されていないため、コンパイル時エラーが発生します。言い換えると、すべてのタイプで機能するわけではありませんが、X<U>(各U)で、後者は適切な定義を持つクラステンプレートの特殊化と一致します。

Xは既知のタイプであると想定していることに注意してください。それはあなたの質問からは明らかではありません。
とにかく、そうではなく、各Xおよび各Uに対してX<U>形式のタイプを受け入れたい場合でも、これを行うことができます。

template<typename T>
class A;

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

最小限の実用的な例として:

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

A<S<int>>A<S<double>>はどちらも問題なく、サンプルがコンパイルされます。コメントを切り替えると、A<char>がまったく定義されていないため、コメントはコンパイルされなくなります。


ちなみに、クラステンプレートの特殊化を使用せず、概念をシミュレートしたい場合(それらはまだ標準の一部ではなく、少なくとも2020年までは含まれないことに注意してください)、次のようなことができます。この:

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

つまり、ジェネリック型Tが与えられた場合、Tis_xuの形式(各U)であるかどうかを検証する別の構造(例ではX<U>)を使用して、実際の型を静的にアサートします。


私の2セント:クラステンプレートの特殊化は、一目で読みやすく、理解しやすいものです。

30
skypjack
template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };

クラステンプレートが与えられました:

template <typename T>
struct X {};

タイプテンプレートパラメータは、以下を使用して制約できます。

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

または:

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

[〜#〜]デモ[〜#〜]

これは、X<U>から派生したタイプでも機能します。

11
Piotr Skotnicki