我想了解我觀察到的C++語言行爲(我理解了它的前半部分)。模板扣除:爲什麼它與繼承一起工作(當它轉換失敗時)?
我的設置:2個模板類:A
和C
。 A
可以轉換爲C
,但不是相反。他們有一些共同的行爲,所以我正在尋找實現一些邏輯只與C
,並依靠從A
到C
轉換,使A
行爲方式與C
相同。
該示例使用運算符重載,但我認爲與功能或方法相同的討論。
我第一次嘗試是使用一個轉換構造函數:
template <class T>
class A {
};
template <class T>
class C {
public:
C() = default;
C(const A<T>&) {};
};
template <class T>
bool operator<(const C<T> &, const C<T> &) {return true;}
int main() {
A<int> a1, a2;
C<int> c1, c2;
c1 = a1; // OK, no-brainer
c1 < c2; // OK, no-brainer
c1 < a1; // template deduction failure
a1 < c1; // template deduction failure
a1 < a2; // template deduction failure
}
其實,這是我認爲我SO和網搜索後明白了上半場。從我收集的模板參數必須完全匹配才能嘗試轉換,並且在這種情況下,如果不考慮可能的轉換,則無法推導出此類轉換,因此不可能進行演繹。如果運營商在C
(但我不喜歡它)製作非模板朋友,這可以規避。
我想接下來的事情就是使用繼承:
template <class T>
class C {
};
template <class T>
class A : public C<T> {
};
template <class T>
bool operator<(const C<T> &, const C<T> &) {return true;}
int main() {
A<int> a1, a2;
C<int> c1, c2;
c1 = a1; // Ok, slicing
c1 < c2; // Ok, no-brainer
c1 < a1; // Ok, but why?
a1 < c1; // Ok, but why?
a1 < a2; // Ok, but why?
}
對於這個我沒有在網絡上找到的解釋(也許我不知道如何搜索)。
我的問題是,爲什麼可以在模板中推導出當A
可轉換爲C
因爲是基類C
(第二種情況),但是當A
只是轉換爲C
(第一種情況)不能推斷?
編輯
正如我已經試過了意見建議的KerrekSB:
template <class T>
bool operator<(const C<T> &, const typename std::common_type<C<T>>::type &) {return true;}
與我的第一種情況下(轉換,而不是繼承)
在這種情況下:
c1 < c2; // OK
c1 < a1; // OK, a1 is converted
a1 < c1; // template deduction failure
a1 < a2; // template deduction failure
使用他的答案我認爲c1 < a1
的作品,因爲第二個參數不是扣除過程的一部分,所以隱式轉換被認爲是第二個參數。
我也試過:
template <class T>
bool operator<(const typename std::common_type<C<T>>::type &, const typename std::common_type<C<T>>::type &) {return true;}
這甚至不能c1 < c2
工作。我認爲這是因爲現在扣除過程中沒有涉及參數。
我對不對?
請同時嘗試'template bool operator <(const C&,const typename std :: common_type > :: type&);'。 –
@KerrekSB謝謝你,我也嘗試過。我有兩個結論嗎? (見編輯) – bolov
是的。在未推導的上下文中,隱式轉換變爲可用。有了兩個非推斷的上下文,就沒有什麼可推斷的了。 –