簡體   English   中英

為類模板的特定嵌套類實現非成員泛型函數

[英]Implementing non-member generic function for specific nested class of a class template

我有以下課程:

template<int P>
struct A {
    struct B {
        auto abs() const { return 1; }
    };
};

具體而言, A應該是模P的整數的有限域, B是表示來自該有限域的元素的類。 然后我有擴展GCD算法的通用實現,它應該使用abs函數。 問題我希望擴展的GCD算法實現在基本類型(int,long等)以及A<P>::B 所以我需要實現一個非成員abs ,它將調用A<P>::B::abs 我嘗試了三種技術,其中兩種不起作用,另一種起作用但不合適。

技術1(不起作用):使用參數依賴查找(ADL)。 定義的體內下列A但身體外部B

auto abs(B const &e) { return e.abs(); }

它不起作用,因為ADL只查找名稱空間而不是類作用域。 更新 :ADL在這里不起作用,因為abs是一個實例方法。 但是根據TC的回答,如果你把它作為朋友功能它可以正常工作,ADL找到它!

技術2(不起作用):在全局或命名空間范圍內使用約束函數模板:

template<int P>
auto abs(typename A<P>::B const &e) { return e.abs(); }

這也不起作用,因為P處於非推導的上下文中。

技術3(有效但不令人滿意):在全局或命名空間范圍內使用無約束函數模板:

template<typename T>
auto abs(T const &e) { return e.abs(); }

這有效。 但是,它不受約束。 我想將此函數模板的實例化僅限制為A<P> (對於事先未知的P )和其他類模板(對於多項式環和字段擴展)。 問題是如果P在非推導的上下文中,我不確定如何使用SFINAE。

template<int P>
struct A {
    struct B {
        auto abs() const { return 1; }
    };
    friend auto abs(B const &e) { return e.abs(); }
//  ^^^^^^
};

然后讓ADL發揮其魔力。

(在B定義它也很好。選擇取決於你。)

這將有效:

namespace impl {
    template <int P>
    struct B {
        auto abs() const { return 1; }
    };

    template <int P>
    auto abs(B<P>& b) {
        return b.abs();
    }
}

template <int P>
struct A {
    using B = impl::B<P>;
    friend B;
};

int main() {
    A<3>::B inner;
    abs(inner);
}

此解決方案使用ADL,因為abs現在與B在同一名稱空間中。 此外,我們避免了具有P在非推導出上下文( P不是一些左邊::再次通過模板參數符號) B 不幸的是,現在B不是A的成員,所以如果你想讓它訪問A的成員,你將不得不把它變成朋友。 之前的解決方案是由於這個答案 我們接下來會改進它。

或者,如果您確實希望B成為A的成員,那么您需要的只是公共外觀以確保正確的重定向:

namespace impl {
    template <typename T>
    struct facade : public T {};

    template <typename T>
    auto abs(facade<T>& b) { return b.abs();    }
}

template <int P>
struct A {
    struct B_ {
        auto abs() const { return 1; }
    };

    using B = impl::facade<B_ >;
};

int main() {
    A<3>::B inner;
    abs(inner);
}

這里的優點是這個公共外觀可以重復使用幾個類,而且它不一定是朋友。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM