1

私が理解していることから、関数の解決は内側のスコープから外側のスコープに発生します。したがって、次の例でMyNamespace::foo()は、両方の場合に実行されます。

foo() {}
namespace MyNamespace
{
    void foo() {}
    void bar() {foo()}
}

foo() {}
namespace MyNamespace
{
    void foo() {}
    void bar() {MyNamespace::foo()} // redundant, or safe and expressive?
}

ただし、 を呼び出すつもりでも、実際には定義されていないMyNamespace::foo()ためMyNamespace::foo()、定義済みのグローバルfoo()が呼び出されるというシナリオが発生する可能性があります。

foo() {printf("I don't think you meant to call me...");}
namespace MyNamespace
{
    //foo() {}
    void bar() {foo()}
}

したがって、名前空間を明示的に記述することは安全で適切な方法でしょうか?それとも、この状況は余分な冗長性を正当化するのに十分な頻度ではないのでしょうか?

4

1 に答える 1

0

関数については、実際のあいまいさまたは潜在的なあいまいさを防ぐ必要がない限り、一般的に名前空間修飾を避けることをお勧めします。これは、名前空間修飾によって引数依存のルックアップが抑制されるため、一般的な (テンプレート) コードでは特に価値があります。実際のクラスで提供される関数を許可すると、より優れたコードになり、破損を回避できる場合があります。例えば:

namespace foo {
    template<typename T>
    struct Ctnr {
        Ctnr();
        Ctnr( Ctnr const & );
        Ctnr &operator=( Ctnr const & );
        ~Ctnr();
        // ...
        friend void swap( Ctnr<T> &, Ctnr<T> & ); // Does not throw.
    };
}
namespace bar {
    template<typename T>
    void exchange( T &lhs, T &rhs ) {
        std::swap( lhs, rhs );
    }

    static foo::Ctnr<string> state;
    void set_state( foo::Ctnr<string> new_state ) {
        // Calls std::swap, which may throw and corrupt state:
        exchange( state, new_state );
    }
}

bar::exchange<T>()ADL を使用して記述されていた場合は、の non-throwingbar::set_state()を使用していたでしょう。のように書いたほうがよいでしょう。fooswap()exchange()using std::swap; swap( lhs, rhs);

于 2013-06-14T23:30:31.747 に答える