簡體   English   中英

當模板化 function 部分依賴於類和自定義模板參數時,將其聲明為友元

[英]Declare templated function as friend when it partially depends on class- and on custom template parameters

作為上一個問題的延續,我現在處於這樣一種情況,我想將 function 聲明為朋友,它取決於 class 模板參數 ( R ) 和其他模板參數 ( Cb ) 的組合。 如何在 class 上下文中正確指定它? 我天真的方法似乎不起作用:

演示

#include <memory>
#include <future>
#include <cstdio>

template <typename Fn, typename R, typename... Args>
concept invocable_r = std::is_invocable_r<R, Fn, Args...>::value;

/* header.hpp */

template <typename T>
class entity;

template <typename R, invocable_r<R> Cb>
auto create_entity(Cb&& fn) -> std::shared_ptr<entity<R>>;

template <typename R>
struct entity
{
    template <invocable_r<R> Cb>
    entity(Cb&& fn)
        : fn_{ std::move(fn) }
    {}

    // *************** Q ***************
    // How to match this declaration to the outside declaration?

    template<invocable_r<R> Cb>
    friend auto create_entity<R>(Cb&& fn) -> std::shared_ptr<entity<R>>;

    // *************** /Q ***************

    std::packaged_task<R()> fn_;
};

/* impl.cpp */

template <typename R, invocable_r<R> Cb>
auto create_entity(Cb&& fn) -> std::shared_ptr<entity<R>> {
    return std::make_shared<entity<R>>(std::forward<Cb>(fn));
}

int main()
{
    create_entity<int>([]{ printf("Hello"); return 10; });
}

錯誤:

<source>:28:17: error: invalid use of template-id 'create_entity<R>' in declaration of primary template
   28 |     friend auto create_entity<R>(Cb&& fn) -> std::shared_ptr<entity<R>>;
      |                 

這里的問題是friend聲明中不允許部分特化(參見https://en.cppreference.com/w/cpp/language/friend#Template_friends )(或一般的 function 模板)。

我能夠使用以下步驟使其工作:

  1. 我們將代碼從create_entity移動到一個帶有struct調用運算符的結構中:
template <typename R, invocable_r<R> Cb>
struct create_entity_s {
    template<typename U = Cb>
    create_entity_s(U&& fn) : m_fn{ std::forward<U>(fn) } {}

    auto operator()() {
        auto ret = std::make_shared<entity<R>>(std::move(m_fn));
        // Test if we're really a friend by accessing a private member
        ret->_i = 5;
        return ret;
    }

    Cb m_fn;
};
  1. 現在我們定義create_function如下,返回上述struct的一個實例:
template <typename R, invocable_r<R> Cb>
auto create_entity(Cb&& fn) {
    return create_entity_s<R, Cb>{ std::forward<Cb>(fn) };
}
  1. 更改friend聲明。 在這里,通過使用U ,我們確保我們不會部分專業化。 然而,這有一個缺點,我們現在與create_entity_s的每個實例都是朋友:
template<typename U, invocable_r<U> Cb>
friend struct create_entity_s;
  1. 使用create_entity (注意末尾的括號以調用 function 對象):
create_entity<int>([]{ printf("Hello"); return 10; })();

這是 Compiler Explorer 上的完整工作示例: https://godbolt.org/z/MPKe5Me6v

我無法僅使用 function 模板使其工作,但struct的技巧肯定有效。 此外,我沒有在這上面花太多時間,所以請原諒任何不完善之處,但總的原則是有效的!

希望這可以幫助!

暫無
暫無

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

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