ClassWithTemplateClass<enumVal>::
是nested name specifier,它又是non-deduced context。由於enumVal
是一個模板參數,它顯示在範圍解析運算符::
的左側,編譯器無法推斷其值。
的<<
操作者可以定義(1)作爲內部TemplateClass
類的朋友:
enum MyEnum { X, Y, Z };
template <MyEnum E>
struct ClassWithTemplateClass
{
template <bool B>
struct TemplateClass
{
friend auto& operator<<(TemplateClass& a, int b)
{
return a;
}
};
};
其中TemplateClass
總是指的ClassWithTemplateClass<?>::TemplateClass<?>
DEMO
或特定實例(2) inside ClassWithTemplateClass
:
enum MyEnum { X, Y, Z };
template <MyEnum E>
struct ClassWithTemplateClass
{
template <bool B>
struct TemplateClass
{
};
template <bool B>
friend auto& operator<<(TemplateClass<B>& a, int b)
{
return a;
}
};
DEMO 2
或,(3),你可以提供爲每個預定義的枚舉值的單獨的操作符定義(儘管它可以具有比定義爲常數更多的值),使得要推導出僅B
需求:
enum MyEnum { X, Y, Z };
template <MyEnum E>
struct ClassWithTemplateClass
{
template <bool B>
struct TemplateClass
{
};
};
template <bool B>
auto& operator<<(ClassWithTemplateClass<X>::TemplateClass<B>& a, int b)
{
return a;
}
template <bool B>
auto& operator<<(ClassWithTemplateClass<Y>::TemplateClass<B>& a, int b)
{
return a;
}
template <bool B>
auto& operator<<(ClassWithTemplateClass<Z>::TemplateClass<B>& a, int b)
{
return a;
}
DEMO 3
,或者(4)店模板參數爲TemplateClass
靜態數據成員,並用它們既能使運營商SFINAE,能夠和檢索其價值S:
enum MyEnum { X, Y, Z };
template <MyEnum E>
struct ClassWithTemplateClass
{
template <bool B>
struct TemplateClass
{
static constexpr MyEnum ClassWithTemplateClass_E = E;
static constexpr bool TemplateClass_B = B;
};
};
template <typename T
, MyEnum E = T::ClassWithTemplateClass_E
, bool B = T::TemplateClass_B>
auto& operator<<(T& a, int b)
{
return a;
}
DEMO 4
作爲另一種選擇,(5),你可以派遣從operator<<
調用另一個函數,並明確指定模板參數,使該簽名是完全按照你想要的,模板參數已知:
enum MyEnum { X, Y, Z };
template <MyEnum E>
struct ClassWithTemplateClass;
template <MyEnum E, bool B>
auto& print(typename ClassWithTemplateClass<E>::template TemplateClass<B>& a, int b);
template <MyEnum E>
struct ClassWithTemplateClass
{
template <bool B>
struct TemplateClass
{
friend auto& operator<<(TemplateClass& a, int b)
{
return print<E, B>(a, b);
}
};
};
template <MyEnum E, bool B>
auto& print(typename ClassWithTemplateClass<E>::template TemplateClass<B>& a, int b)
{
return a;
}
DEMO 5
嘗試用你的錯誤信息搜索:HTTP:// STAC koverflow.com/search?q=error%3A+declaration+of+%27operator%3C%3C%27+as+non-function。有不少問題(和答案)。 –
你真的不能在類模板定義之外寫這個。使用'typename'和'template'可以編譯它們,但是整個事情是一個非推導的上下文,所以除非明確地做 - 否則操作符將永遠不會被調用 - 這會破壞整個操作符的重載點。 –