4

私は、C++11 には十分な静的チェック (コンパイル時間) があり、C++11 の概念チェック (削除) であるべきだった部分の大部分を実装できることを読みました。(削除された概念に関する最近の質問のコメントでこれを読みました... - その質問は建設的ではないためすぐに閉じられました)。

以下の C++03 コードは、クラス内のメンバー関数の存在のみをチェックします (テンプレート クラスが動作するクラス)。検索される 4 つのメンバー関数を次に示します。私は常に同じパターンを使用します。

  • 関数のプロトタイプの typedef を定義するための typedef
  • 型名 TExtension がそのようなメンバー関数を定義していない場合、または別のプロトタイプを持っている場合にコンパイルを中断する static_cast の呼び出し

コードは次のとおりです。

template <typename TExtension>
class
{
...
    void checkTemplateConcept()
    {
        typedef unsigned long (TExtension::*memberfunctionRequestedId)();
        static_cast<memberfunctionRequestedId>(&TExtension::getRequestId);

        typedef eDirection (TExtension::*memberfunctionDirection)();
        static_cast<memberfunctionDirection>(&TExtension::getDirection);

        typedef eDriveWay (TExtension::*memberfunctionDriveWay)();
        static_cast<memberfunctionDriveWay>(&TExtension::getDriveWay);

        typedef unsigned long (TExtension::*memberfunctionCycleId)();
        static_cast<memberfunctionCycleId>(&TExtension::getCycleId);
    }
}

これは私のコードの一部でしたが、完全にC++03に基づいていました。これらの新しいC++ 11機能を使用して、喜んで書き直します...代わりにここで何を使用する必要がありますか?

4

2 に答える 2

6

C ++ 11を使用すると、コンパイラに次のように適切なエラーメッセージを出力させることができますstatic_assert

typedef unsigned long (TExtension::*required_type)();
typedef decltype(&TExtension::getRequestId) actual_type;

static_assert(std::is_same<required_type, actual_type>::value,
     "The type of getRequestId must be unsigned long (C::*)()");

これで、メンバー関数のタイプが一致しない場合、コンパイラーは次の役立つメッセージを出力します。

"The type of getRequestId must be unsigned long (C::*)()"

必要に応じて、よりわかりやすくすることができます。:-)

于 2013-01-18T17:16:42.110 に答える
0

はい、C++11 では、SFINAE は式に拡張されたので、次のようis_t_extensionにメンバー関数の存在を検出するような特性を定義できます。

template<class... T>
struct holder
{
    typedef void type;
};

template<class T, class=void>
struct is_t_extension
: std::false_type
{};

template<class T, class=void>
struct is_t_extension<T, typename holder<
    decltype(std::declval<T>().getRequestId),
    decltype(std::declval<T>().getDirection),
    decltype(std::declval<T>().getDriveWay),
    decltype(std::declval<T>().getCycleId)
>::type>
: std::true_type
{};

これで、その存在を確認するだけです。上記を拡張して有効な署名を検出するか、代わりにTickライブラリを使用してトレイトを記述できます。

TICK_TRAIT(is_t_extenstion)
{
    template<class T>
    auto requires_(T&& x) -> TICK_VALID(
        returns<unsigned long>(x.getRequestId),
        returns<eDirection>(x.getDirection),
        returns<eDriveWay>(x.getDriveWay),
        returns<unsigned long>(x.getCycleId)
    );
};

次に、クラスで a を使用しstatic_assertてエラーを報告できます。

template <typename TExtension>
class foo
{
    static_assert(is_t_extension<TExtension>(), "Not a TExtension");
};

または、特殊化を許可する場合は、次を使用できますTICK_CLASS_REQUIRES

template <typename TExtension, class=void>
class foo;

template <typename TExtension>
class foo<TExtension, TICK_CLASS_REQUIRES(is_t_extension<TExtension>())>
{
    ...
};
于 2014-07-01T22:40:06.227 に答える