[英]Inferring return type of templated member functions in CRTP
是否可以推斷CRTP基類中模板化成員函數的返回類型?
推斷參數類型效果很好,但它返回類型失敗。 考慮下面的例子。
#include <iostream>
template <typename Derived>
struct base
{
template <typename R, typename T>
R f(T x)
{
return static_cast<Derived&>(*this).f_impl(x);
}
};
struct derived : base<derived>
{
bool f_impl(int x)
{
std::cout << "f(" << x << ")" << std::endl;
return true;
}
};
int main()
{
bool b = derived{}.f(42);
return b ? 0 : 1;
}
這會產生以下錯誤:
bool b = derived{}.f(42);
~~~~~~~~~~^
crtp.cc:7:5: note: candidate template ignored: couldn't infer template argument 'R'
R f(T x)
^
1 error generated.
我的直觀假設是,如果編譯器能夠為f
的參數推斷類型int
,它也應該適用於返回bool
,因為這兩種類型在模板實例化時都是已知的。
我嘗試使用尾隨返回類型函數語法,但后來找不到要放入decltype
的工作表達式。
對於函數具有一個或多個模板化參數的情況,DietmarKühl提供了一種基於使用間接層延遲模板實例化的解決方案。 不幸的是,當基類函數沒有任何參數時,這不起作用,如下所示:
template <typename R>
R g()
{
return static_cast<Derived&>(*this).g_impl();
}
嘗試使用相同的技術失敗,因為不存在依賴類型。 如何處理這種情況?
正如Johannes Schaub所指出的,C ++ 11具有默認模板參數,因此始終可以使g
依賴於任意類型,然后應用Dietmar的解決方案:
template <typename T = void>
auto g() -> typename g_impl_result<Derived, T>::type
{
return static_cast<Derived&>(*this).g_impl();
}
這個問題在C ++ 14中不再存在,因為我們對正常函數有返回類型推導,允許我們簡單地寫:
template <typename Derived>
struct base
{
template <typename T>
auto f(T x)
{
return static_cast<Derived&>(*this).f_impl(x);
}
auto g()
{
return static_cast<Derived&>(*this).g_impl();
}
};
struct derived : base<derived>
{
bool f_impl(int x)
{
return true;
}
double g_impl()
{
return 4.2;
}
};
額外的間接是你的朋友:
template <typename D, typename T>
struct f_impl_result
{
typedef decltype(static_cast<D*>(0)->f_impl(std::declval<T>())) type;
};
template <typename Derived>
struct base
{
template <typename T>
auto f(T x) -> typename f_impl_result<Derived, T>::type
{
return static_cast<Derived&>(*this).f_impl(x);
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.