有沒有辦法使模板推導與(隱式)轉換一起作業?像下面的例子:
template<typename T> struct A {};
template<typename T> struct B
{
B(A<T>); // implicit A->B conversion
};
template<typename... Ts> void fun(B<Ts>...);
int main()
{
A<int> a;
fun(B(a)); // works
fun(a); // does not work (deduction failure)
}
我的想法:
- 如果
A是 的子類B,則一切正常。這意味著演繹可以使用向上轉換進行隱式轉換。所以它不能使用建構式進行隱式轉換似乎很奇怪。 - 原則上可以多載
funforA和B,但是對于多個引數,組合太多了 - 添加扣除準則 (
template<typename T> B(A<T>)->B<T>;) 不會改變任何內容。
編輯:一些背景關系:在我的實際代碼中,A是一個(大)容器,B是一個輕量級的非擁有視圖物件。這種情況類似于在 的推導程序中std::vector<T>不能隱式轉換為 的事實,即使對于任何具體的,也存在這樣的轉換。std::span<T>TT
uj5u.com熱心網友回復:
我認為你可以提供不同的多載func 然后你想出并解決你的多種可能轉換的問題。
template<typename T> struct A {};
template<typename T> struct C {};
template<typename T> struct B
{
B(A<T>) {}
B(C<T>) {}
};
template<typename... Ts>
void fun(B<Ts>...)
{
LOGFUN;
}
template<typename... Ts>
void fun(Ts...arg)
{
LOGFUN;
fun(B{arg}...);
}
int main()
{
A<int> a;
C<int> c;
fun(B(a));
fun(a);
fun(c, a, c);
}
https://godbolt.org/z/ne31z8Kfa
uj5u.com熱心網友回復:
模板引數推導不考慮任何潛在的型別轉換 - 主要是因為推導發生在任何此類轉換發生之前。
基本上,當編譯器看到 時fun(a),它首先收集一組foo有資格為該呼叫提供服務的函式。如果foo找到函式模板,編譯器會嘗試通過將模板引數替換為呼叫陳述句中傳遞的引數型別來從中生成具體函式。這就是模板引數推導發生的地方。這里不會發生型別轉換,因為沒有要轉換的具體型別。在您的示例中,B<T>不是要轉換為的型別,因為T未知并且無法從 type 的引數中發現它A<int>。也不知道是否B<T>可以構造的任意實體,A<int>因為 的不同專業化B可能有不同的建構式集。因此,在您的情況下,扣除失敗。
如果推導成功,則將具體函式(具有推導的引數型別)添加到候選集。
當收集到候選集時,然后選擇最佳匹配候選。此時考慮引數轉換。由于候選物件不再是模板,并且轉換的目標型別是已知的,因此轉換是可能的。
您可以做些什么來解決它是允許編譯器也推匯出模板,然后B<T>顯式構造:
template<typename... Ts> void fun_impl(B<Ts>...);
template<template<typename> class X, typename... Ts>
std::enable_if_t<(std::is_constructible_v<B<Ts>, X<Ts>> && ...)> fun(X<Ts>... args)
{
fun_impl(B<Ts>(args)...);
}
int main()
{
A<int> a;
fun(B(a)); // works, instantiates fun<B, int>
fun(a); // works, instantiates fun<A, int>
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/312602.html
上一篇:如何使用模板使不必要的長代碼緊湊
