17

C++ の (非常に多くの) 残念な設計上の欠陥の 1 つは、テンプレート メタプログラミングを使用する場合、実装をインターフェイスから分離することが基本的に不可能であることです。

私のライブラリには、次のようなものがあります。

template <typename Ma, typename Mb>
typename boost::enable_if_c<
            detail::IsMatrix<Ma>::val and detail::IsMatrix<Mb>::val and
            detail::MatrixDimensionCheck<Ma,Mb>::isStaticMatch, 
        bool>::type
operator==(const Ma &a, const Mb &b) {
    return detail::matrixEqual(a,b);
}

これが読めなくても、私はあなたを責めません。この混乱のほとんどは、引数が行列で次元が一致する場合は戻り値の型を定義し、boolそれ以外の場合は未定義に定義するだけです (したがって、この演算子が他の重要なものを隠すのを防ぐために SFINAE に依存しています)。

本質的に静的な型チェック関数の内臓が通常の C++ 関数のシグネチャに埋め込まれているため、これらの実装内臓が生成されたドキュメントに表示されます。

ユーザーがこれを読む必要はありません。彼らが知る必要があるのは、この関数が a を返すことだけですbool(上記を読んでも、これを知ることはほとんど不可能です)。ドキュメントでは、この演算子が行列のみを受け入れることを平易な英語で簡潔に説明できます。

そのタイプの混乱を としてレンダリングするように Doxygen を説得する方法はありboolますか? (これをコードで直接クリーンアップする方法は多かれ少なかれないと思いますが、何か考えられることがあればアイデアを歓迎します)。

4

5 に答える 5

1

戻り値の型として表示するように Doxygen を説得するbool: 私が知っている唯一の方法は Raffi の答えであり、おそらく Doxygen から実際の関数を隠したいと思うでしょう (これを行うにはいくつかの方法があります)。

再クリーンアップ:これは次のようになります

template <typename Ma, typename Mb>
typename bool_isEqual<Ma, Mb>::type 
operator==(const Ma &a, const Mb &b)
...

Whereはすべてのbool_isEqualテンプレート タイプ ロジックをカプセル化し、適切な場合は toにします。(この名前が選択されたのは、同様の構造を持つ他のテンプレート関数が返され、他の条件を持つことが想定されているためです。)typedeftypeboolbool_isEqualbool

これが一貫して行われていれば、おそらく十分に読みやすいでしょう。

于 2013-12-09T19:41:46.987 に答える
1

次の方法が非常に明確であることがわかりました。

  1. Doxyfile に PREDEFINED = DOXYGEN を追加します。
  2. ソース コードで、SFINAE 関数を次のように囲みます。///@cond .... ///@endcond
  3. 単純なテンプレート化された関数宣言を 内のソース コードに入れる#ifdef DOXYGENと、通常のコンパイルでは見えなくなります。観察:

    ///@cond
    template <typename Ma, typename Mb>
    typename boost::enable_if_c<
        detail::IsMatrix<Ma>::val and detail::IsMatrix<Mb>::val and
        detail::MatrixDimensionCheck<Ma,Mb>::isStaticMatch, 
        bool>::type
    operator==(const Ma &a, const Mb &b) {
        return detail::matrixEqual(a,b);
    }
    ///@endcond
    #ifdef DOXYGEN
        ///Documentation for your function...
        template<typename Ma, typename> operator==(const Ma &a, const Mb &b);
    #endif
    
于 2014-03-27T12:30:01.653 に答える
-1

これはあなたのために働くかもしれないと思います。明らかに、それはあなたのものよりも単純な例ですが、文書化enable_ifされていないがSFINAEを提供する別の「隠し」関数を呼び出さずに、文書化されたテンプレート関数を使用するという基本的な考え方です。

// Ignore this function in doxygen
template <typename T>
typename boost::enable_if<boost::is_unsigned<T>, bool>::type
test_hidden(T t) {
    return true;
}

template <typename T>
typename boost::disable_if<boost::is_unsigned<T>, bool>::type
test_hidden(T t) {
    return false;
}

// Document this function
template <typename T>
bool test(T t)
{
    return test_hidden(t);
}

int main()
{
   unsigned int a = 1;
   int b = 0;

   std::cout << test(a) << std::endl; // true
   std::cout << test(b) << std::endl; // false

   return 0;
}
于 2013-08-08T09:36:18.317 に答える