4

私はテンプレート関数を持っています、例えば、

template<class T> 
void mysort(std::vector<T>& vec)
{
    size_t b, m, e,
    ...
    mysort(vec, b, m, e);
}

template<class T>
void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)
{
     size_t x, y, z;
     ...
     mysort (vec, x, y, z);
}

パブリック インターフェイスは、ベクトル参照のみを受け取るインターフェイスです。クライアントコードができないように、もう1つの実装を非表示にしたいと思います

mysort(vec, a, b, c);

クラスを作って実装関数をprivate staticにするのは違和感があり、匿名名前空間を使ってみたり、

namespace abc 
{
    namespace 
    {
        template<class T>
        void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
    }

    template<class T> 
    void mysort(std::vector<T>& vec)...

}

それは役に立ちますが、正確にはノックアウトではありません...

#include "mysort.h"

int main()
{
    ...
    abc::mysort(vec, a, b, c); // this won't compile, good
}

ただし、次のように変更すると:

#include "mysort.h"

using namespace abc;

int main()
{
    ...
    mysort(vec, a, b, c); // it compiles and runs!!
}

x86_64でgcc Ubuntu 4.4.3-4ubuntu5を使用しています。なぜそれがディレクティブを使用してコンパイルされ、修飾名ではコンパイルされないのか、そして私が望むものを達成するためのより良い方法があるかどうかを誰かが説明できますか?

4

2 に答える 2

6

これの一般的なイディオムは、内部で使用されるコードのみを対象とした「詳細」名前空間を作成することです。

namespace abc 
{
    namespace detail
    {
        template<class T>
        void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
    }

    template<class T> 
    void mysort(std::vector<T>& vec)...

}

名前のない名前空間の動作に関する質問に答えるには:

名前のない名前空間 (匿名名前空間とは呼ばれません) は、少し変わった名前が付けられています。名前は付けられていませんが、実際にはコンパイラが一意の内部名を生成します。あなたの例は次と同等です:

namespace abc 
{
    namespace def // lets say 'def' is unique.
    {
        template<class T>
        void mysort(std::vector<T>& vec, size_t b, size_t m, size_t e)..
    }
    using namespace def;

    template<class T> 
    void mysort(std::vector<T>& vec)...

}

名前のない例と同じように動作することに気付くでしょう。abc::mysort(vec, 1, 2, 3)ここではできませんが、できますusing namespace abc; mysort(vec, 1, 2, 3)

これは、 が 2つではなく、とabc::mysortだけであるために発生します。実際の を宣言すると、 によって持ち込まれたものは隠されます。1-param をコメントアウトすると、実際には と言えることに注意してください。abc::def::mysortabc::mysortabc::mysortusing namespace defmysortabc::mysort(vec, 1, 2, 3)

非表示になっているため、 への修飾呼び出しabc::mysortは明示的に参照する必要がありabc::mysort、1-param バージョンのみが検出されます。

ただし、 を介した非修飾呼び出しではusing namespace abc; mysort(vec, 1, 2, 3)、ADL を使用して、一致する使用可能な関数を見つけることができます。

于 2012-12-27T19:52:42.860 に答える
0

実際には、後のバージョンの gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) と -std=c++0x でさらにテストを行いましたが、まさに期待どおりの動作をします。

メイン ファイルでは、 using ディレクティブまたは修飾名を使用しても、それ自体が別の名前空間内にある匿名名前空間内の関数を呼び出すことはできません。

その理由は、名前のない名前空間にはデフォルトで内部リンケージがあるという最新の標準をコンパイラが確認しているためだと思います。

名前のない名前空間のアプローチは、古い「詳細」名前空間の慣行よりも優先されるべきだと私には思えます。

于 2013-01-13T16:18:17.443 に答える