سؤال

std::swap() يستخدم من قبل العديد من الأمراض المنقولة جنسيا حاويات (مثل std::list و std::vector) أثناء الفرز وحتى المهمة.

ولكن std تنفيذ swap() هو معمم جدا و غير فعالة بدلا من العرف أنواع.

وبالتالي كفاءة يمكن الحصول عليها عن طريق إثقال std::swap() مع العرف نوع محددة للتنفيذ.ولكن كيف يمكن تنفيذ ذلك سيتم استخدامها من قبل std الحاويات ؟

هل كانت مفيدة؟

المحلول

الطريقة الصحيحة الزائد المبادلة هو أن يكتب في نفس مساحة الاسم مثل ما أنت مبادلة ، بحيث يمكن العثور عليها عن طريق الحجة التي تعتمد على بحث (ADL).ومن السهل القيام به هو:

class X
{
    // ...
    friend void swap(X& a, X& b)
    {
        using std::swap; // bring in swap for built-in types

        swap(a.base1, b.base1);
        swap(a.base2, b.base2);
        // ...
        swap(a.member1, b.member1);
        swap(a.member2, b.member2);
        // ...
    }
};

نصائح أخرى

الاهتمام Mozza314

هنا هو محاكاة آثار عامة std::algorithm الدعوة std::swap, و وجود المستخدم تقديم مبادلة في مساحة الأمراض المنقولة جنسيا.وهذا هو تجربة هذه المحاكاة يستخدم namespace exp بدلا من namespace std.

// simulate <algorithm>

#include <cstdio>

namespace exp
{

    template <class T>
    void
    swap(T& x, T& y)
    {
        printf("generic exp::swap\n");
        T tmp = x;
        x = y;
        y = tmp;
    }

    template <class T>
    void algorithm(T* begin, T* end)
    {
        if (end-begin >= 2)
            exp::swap(begin[0], begin[1]);
    }

}

// simulate user code which includes <algorithm>

struct A
{
};

namespace exp
{
    void swap(A&, A&)
    {
        printf("exp::swap(A, A)\n");
    }

}

// exercise simulation

int main()
{
    A a[2];
    exp::algorithm(a, a+2);
}

بالنسبة لي هذا يطبع:

generic exp::swap

إذا كان المترجم يطبع شيئا مختلفا فإنه لا بشكل صحيح تنفيذ "المرحلة الثانية بحث" القوالب.

إذا كان المترجم هو المطابقة (أي من C++98/03/11), ثم أنها سوف تعطي نفس الناتج تظهر.و في هذه الحالة بالضبط ما كنت تخشى سوف يحدث لا يحدث.ووضع الخاص بك swap في مساحة الاسم std (exp) لم يمنع ذلك من الحدوث.

ديف أنا و كل أعضاء اللجنة وقد تم العمل في هذا المجال من معيار العقد (وليس دائما في اتفاق مع بعضها البعض).ولكن هذه القضية قد تم تسويتها منذ وقت طويل, و نحن اتفقنا على الكيفية التي تم تسويتها.تجاهل ديف رأي الخبراء/الإجابة في هذا المجال على مسؤوليتك الخاصة.

هذه المسألة التي خرجت إلى النور بعد C++98 نشرت.بدءا من 2001 ديف و بدأت العمل في هذا المجال.و هذا هو الحل الحديثة:

// simulate <algorithm>

#include <cstdio>

namespace exp
{

    template <class T>
    void
    swap(T& x, T& y)
    {
        printf("generic exp::swap\n");
        T tmp = x;
        x = y;
        y = tmp;
    }

    template <class T>
    void algorithm(T* begin, T* end)
    {
        if (end-begin >= 2)
            swap(begin[0], begin[1]);
    }

}

// simulate user code which includes <algorithm>

struct A
{
};

void swap(A&, A&)
{
    printf("swap(A, A)\n");
}

// exercise simulation

int main()
{
    A a[2];
    exp::algorithm(a, a+2);
}

الناتج هو:

swap(A, A)

التحديث

ملاحظة تم أن:

namespace exp
{    
    template <>
    void swap(A&, A&)
    {
        printf("exp::swap(A, A)\n");
    }

}

يعمل!فلماذا لا تستخدم هذا ؟

النظر في القضية التي A هي فئة القالب:

// simulate user code which includes <algorithm>

template <class T>
struct A
{
};

namespace exp
{

    template <class T>
    void swap(A<T>&, A<T>&)
    {
        printf("exp::swap(A, A)\n");
    }

}

// exercise simulation

int main()
{
    A<int> a[2];
    exp::algorithm(a, a+2);
}

الآن أنها لا تعمل مرة أخرى.:-(

إذا كنت قد وضعت swap في مساحة الأمراض المنقولة جنسيا و يكون ذلك العمل.ولكن سوف تحتاج إلى تذكر أن وضع swap في A's الاسم عن الحال عندما يكون لديك قالب: A<T>.وأن كلا الحالات سوف تعمل إذا وضعت swap في A's مساحة, فمن الأسهل أن نتذكر (و تعليم الآخرين) أن اقترح طريقة واحدة.

غير مسموح لك (من C++ القياسية) الزائد std::مبادلة ، ومع ذلك أنت على وجه التحديد يسمح لإضافة قالب التخصصات الخاصة بك أنواع مساحة الأمراض المنقولة جنسيا.E. g.

namespace std
{
    template<>
    void swap(my_type& lhs, my_type& rhs)
    {
       // ... blah
    }
}

ثم الأعراف في الأمراض المنقولة جنسيا حاويات (و في أي مكان آخر) واختيار التخصص الخاص بك بدلا من عام واحد.

نلاحظ أيضا أن توفير قاعدة الطبقة تنفيذ المبادلة ليست جيدة بما فيه الكفاية بالنسبة مشتقة أنواع.E. g.إذا كان لديك

class Base
{
    // ... stuff ...
}
class Derived : public Base
{
    // ... stuff ...
}

namespace std
{
    template<>
    void swap(Base& lha, Base& rhs)
    {
       // ...
    }
}

هذا العمل بالنسبة فئات أساسية ، ولكن إذا كنت في محاولة لمبادلة اثنين المستمدة من الكائنات فإنه سيتم استخدام إصدار عام من الأمراض المنقولة جنسيا لأن قالب مبادلة تطابق تام (و يتجنب مشكلة فقط مبادلة 'القاعدة' أجزاء من المستمدة من الكائنات).

ملاحظة:لقد تم تحديث هذا إلى إزالة الخطأ في البتات من آخر الجواب.انطلقي(شكرا puetzk و j_random_hacker لافتا بها)

في حين أنه من الصحيح أن لا عموما إضافة الأشياء إلى std::مساحة, إضافة قالب التخصصات الأنواع المعرفة من قبل المستخدم على وجه التحديد هو مسموح به.إثقال وظائف لا.هذا هو فرق دقيق :-)

17.4.3.1/1 هو غير معروف عن C++ برنامج لإضافة الإعلانات أو تعريفات إلى مساحة الأمراض المنقولة جنسيا أو مساحات مع مساحة الأمراض المنقولة جنسيا ما لم يذكر خلاف ذلك المحدد.برنامج إضافة قالب التخصصات لأي المكتبة القياسية قالب مساحة الأمراض المنقولة جنسيا.مثل هذا التخصص (كاملة أو جزئية) من المكتبة القياسية النتائج في غير معرف السلوك إلا إذا كان الإعلان يعتمد على المعرفة من قبل المستخدم اسم الخارجية الربط و ما لم قالب التخصص تلبي المكتبة القياسية متطلبات القالب الأصلي.

التخصص: الأمراض المنقولة جنسيا::مبادلة تبدو مثل:

namespace std
{
    template<>
    void swap(myspace::mytype& a, myspace::mytype& b) { ... }
}

بدون قالب<> بت سيكون الزائد الذي هو غير معروف ، بدلا من التخصص ، مما هو مسموح به.@Wilka هي تشير إلى اقتراب تغيير الاسم الافتراضية قد تعمل مع رمز المستخدم (بسبب كونيغ بحث مفضلا مساحة-الإصدار أقل) ولكنها ليست مضمونة في الواقع ليس من المفترض أن (المحكمة الخاصة بلبنان التنفيذ يجب استخدام المؤهل بالكامل std::مبادلة).

هناك موضوع على شركات.لانغ.c++.أدار مع طويلة dicussion الموضوع.الأكثر من ذلك هو حول جزئية التخصص ، على الرغم من (الذي يوجد حاليا أي وسيلة جيدة للقيام).

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top