web-dev-qa-db-ja.com

static_assertを介してテンプレートタイプを適用する

static_assertの有用性を理解しようとしていますが、それが設計の実施に役立つかどうか、また役立つ場合はどのように役立つかを知りたいと思います。

テンプレートタイプのサイズに基づいて部分的に特殊化された別のテンプレートクラス内に独自の実装を隠す一般的なテンプレートクラスがあります。この設計の概要は次のとおりです。

template <class T, size_t S = sizeof(T)>
struct Helper;

template <class T>
struct Helper<T, sizeof(long)>
{
    static T bar();
};

// ... other specializations ...

template <class T>
class Foo
{
public:

    T bar()
    {
        return Helper<T>::bar();
    }
};

Fooは、TのサイズがHelperの特殊化によってサポートされている場合にのみサポートされます。たとえば、Foo<long>Foo<unsigned long>はどちらもサポートされています。ただし、ユーザーがFoo<bool>を作成しようとしているとします。通常、これはエラーを生成します。これは、boolの-​​Helperの特殊化が定義されていないためです。これは、意図された動作です。

このデザインでstatic_assertを使用して、このインターフェイスのユーザーにより役立つエラーを提供する方法はありますか?

さらに、サイズが正しい場合でも、ユーザーが特定のタイプを使用することを制限したいと思います。たとえば、Foo<float>は許可されません。今のところ、これを実施するために私が知っている唯一の方法は、ドキュメントの太字のコメントを使用することです。 :)

19
Zeenobit

ここで回答とコメントを組み合わせることで、この問題のより良い解決策を見つけました。

静的型チェッカーを次のように定義できます。

template <class A, class B>
struct CheckTypes
{
    static const bool value = false;
};

template <class A>
struct CheckTypes<A, A>
{
    static const bool value = true;
};

そのような構造体が標準ライブラリにすでに存在するかどうかはわかりません。とにかく、次にFooで、次を使用してタイプとサイズを確認できます:

static_assert((sizeof(T) == sizeof(long) || sizeof(T) == sizeof(int)) && !CheckTypes<T, float>::value, "Error!");
1
Zeenobit

テンプレートクラスの特殊化に対してのみ機能する場合は、デフォルトのテンプレートクラスに静的アサートを発生させます。

template <class T, size_t S = sizeof(T)>
struct Helper
{
   static_assert(sizeof(T) == -1, "You have to have a specialization for Helper!" );
}

デフォルトのテンプレートクラスは、より優れた特殊化がない場合にのみ選択されるため、アサートが発生します。

同じ手法を使用して型を禁止することもできますが、静的アサートチェックに使用される別のテンプレートパラメータが必要になります。

template <class T, class G = T, size_t S = sizeof(T)>
struct Helper
{
   static_assert(sizeof(G) == -1, "You have to have a specialization for Helper!" );
}

template <class G>
struct Helper<float,G>
{
   static_assert(sizeof(G) == -1, "You can't use float !" );
}

template <>
struct Helper<int>
{
 //This is a good specialization
};

次に、これらの変数でそれを試すことができます:

Helper<bool> a;  //"You have to have a specialization for Helper!"
Helper<float> b; //"You can't use float !"
Helper<int> c;   //compiles OK
20
Yochai Timmer

http://en.cppreference.com/w/cpp/header/type_traits

_std::is_base_of_と_std::is_convertible_は最初の問題に役立つ可能性があり、2番目の問題については

static_assert(!std::is_same<float,T>(),"type can't be float");

うまくいけば、これは、OPが質問されてから4年以内に答えを見つけたと仮定して、この質問に遭遇した他の誰かを助けるでしょう:)

5
Austin_Anderson