我遇到了一個基於參數包的特性啓用/禁用重載的問題。這是我想回答的另一個問題。我有一個靜態的go()
函數,如果所有的Mixins
類型都有一個靜態的check()
方法,應該調用它。同樣,應該有另一種靜態go()
方法,如果Mixins
包不有一個check()
方法應該被調用。我試圖創造條件讓基於這一政策重載,但由於某些原因,當我把它叫做它選擇第二過載,它試圖撥打handle()
:如何正確處理這個SFINAE?
template<class T, class...>
using first = T;
template<class... Mixins>
struct Checker
{
public:
template<class =
first<void,
typename std::enable_if<has_check<Mixins>::value>::type...>>
static void go()
{
auto x{ (Mixins::check(), 0)... };
(void)x;
}
static void go()
{
auto x{ (Mixins::handle(), 0)... };
(void)x;
}
};
struct A { static void check() { std::cout << "check() "; } };
struct B { static void check() { std::cout << "check() "; } };
int main()
{
Checker<A, B>::go();
}
我得到一個錯誤說A
沒有任何成員名字handle()
。這一直在困擾着我,但我無法找到解決辦法。我如何解決這個問題?如何根據參數包正確協調重載分辨率?
無關:不知道你是否在意,但是當'Mixins'爲空時,你的'auto x {...}'行會出現編譯錯誤。 'auto x {};'是不合格的。通常的解決方法是在初始化程序中添加一個額外的前導0:'auto x {0,(Mixins :: check(),0)...};' – Casey
@Casey感謝您指出這一點。下面的'0'也很重要嗎? – 0x499602D2
是的。一個支撐初始化器列表是一個方便的地方來擴展參數包,以保證按順序評估。此代碼使用我稱之爲「初始化程序列表技巧」來評估任意包擴展表達式 - 在本例中爲'Mixins :: check()'和/或'Mixins :: handle()' - 將其用作副作用在構建一個加載的初始整數列表。擴展中每個出現的'(Mixins :: check(),0)'評估一個'check'函數,並且 - 使用逗號運算符 - 拋出結果並在初始化列表中粘貼一個「0」。 – Casey