[英]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 模板)。
我能夠使用以下步驟使其工作:
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;
};
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) };
}
friend
聲明。 在這里,通過使用U
,我們確保我們不會部分專業化。 然而,這有一個缺點,我們現在與create_entity_s
的每個實例都是朋友:template<typename U, invocable_r<U> Cb>
friend struct create_entity_s;
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.