c++ - لماذا لا تعمل remove_reference على الوظائف؟




templates types (2)

النوع الذي لديك ليس مرجعًا لوظيفة ، ولكنه دالة ذات مؤهل مرجعي .

static_assert(std::is_same_v<void()&, void()&>);
static_assert(!std::is_same_v<void()&, void(&)()>);
static_assert(std::is_same_v<void(&)(), void(&)()>);
static_assert(std::is_same_v<void(), std::remove_reference_t<void(&)()>>);

اصطدم بشيء غريب عند تنفيذ بعض القوالب metaprogramming في اليوم الآخر. يتعلق الأمر أساسًا بهذا التأكيد وليس النجاح (كما كنت أتوقع).

static_assert(std::is_same_v<void(), std::remove_reference_t<void()&>>);

في البداية اعتقدت أنني ارتكبت خطأً نحويًا في تحديد مرجع وظيفة ، لكن هذا التأكيد ينجح ، مما يدل على أن الأمر ليس كذلك.

static_assert(std::is_same_v<void()&, void()&>);

لقد حاولت أيضًا تطبيق remove_reference بنسخ المصدر من cppreference لكن ذلك لم ينجح أيضًا. ما الذي يجري هنا؟


مرحبًا بك في عالم أنواع الوظائف البغيضة.

void() & لا يعد إشارة إلى void() . طريقة تهجئة ذلك ستكون void(&)() (والتي إذا قمت remove_reference_t ، remove_reference_t مرة أخرى void() - وهذا يعني أن remove_reference_t يعمل على مراجع للوظائف ، إذا كان ما تقدمه بالفعل مرجعًا لنوع الوظيفة ).

ما void() & فعلا يشير إلى نوع وظيفة عضو مؤهل مرجع بعد تجريده من الفصل. هذا هو:

struct C {
    void f() &;
};

نوع &C::f void (C::*)() & . ولكن يمكن كتابة جميع المؤشرات إلى الأعضاء كـ TC::* لبعض الأنواع T ، وفي هذه الحالة سيكون النوع T void() & .

انظر أيضًا P0172 .





c++17