[英]Template function specialization for specific template ( not type )
我有一些模板化的 class 類型,例如 A、B、C,如下所示:
template < typename T >
class A{};
template < typename T >
class B{};
template < typename T >
class C{};
現在我想要一個 function 通常接受任何類型,例如:
template < typename T>
void Func()
{
std::cout << "Default " << __PRETTY_FUNCTION__ << std::endl;
}
現在我想專門化 function 以僅接受給定模板類之一,例如:
template < typename T>
void Func<A<T>>()
{
std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}
這是不允許的,因為它只是部分專業化。 好的。
我認為concept
可能會有所幫助,但感覺我想得太復雜了。 我的解決方案是:
template < typename T, template <typename > typename OUTER >
bool Check;
template < typename INNER, template < typename > typename OUTER, template < typename> typename T>
constexpr bool Check< T<INNER>, OUTER > = std::is_same_v< OUTER<INNER>, T<INNER>>;
template < typename T >
concept IsA = Check< T, A >;
template < typename T >
concept IsB = Check< T, B >;
template < IsA T >
void Func()
{
std::cout << "All A Types " << __PRETTY_FUNCTION__ << std::endl;
}
template < IsB T >
void Func()
{
std::cout << "All B Types " << __PRETTY_FUNCTION__ << std::endl;
}
int main()
{
Func<A<int>>();
Func<B<int>>();
Func<C<int>>();
}
我覺得有點復雜。 可以簡化嗎? 如果可以刪除Check
模板會很好。 任何想法?
在此處實時查看完整示例
一種常見的解決方法是 go ,如下所示:
template <typename T>
struct FuncImpl {
static void Run() { std::cout << "Default"; }
};
template <typename T>
struct FuncImpl<A<T>> {
static void Run() { std::cout << "Specialized for A<T>"; }
};
template <typename T>
void Func() { FuncImpl<T>::Run(); }
Function 模板不能部分特化,但 class 模板可以; 所以我們只是將前者委托給后者。
我覺得有點復雜。 可以簡化嗎? 如果可以刪除檢查模板會很好。 任何想法?
事實上,您需要為每個 class 模板提供一個新概念。 寫一個通用的、可復用的概念,使用起來不再復雜。
template <typename T, template <typename...> class TT>
constexpr bool is_instantiation_of_v = false;
template <template <typename...> class TT, typename... TS>
constexpr bool is_instantiation_of_v <TT<TS...>, TT> = true;
template <class C, template<typename...> class TT>
concept instantiation_of = is_instantiation_of_v<C, TT>;
與您的原理相同,除了檢查器可用於采用任意數量的 arguments 類型的模板。 同時,該概念接受相同的參數。 第一個參數有特殊含義,隱式理解為簡寫語法中的約束模板參數。 rest(模板模板參數)必須明確給出。
如何使用? 像這樣
template <instantiation_of<A> T>
int Func()
{
return 'A';
}
template <instantiation_of<B> T>
int Func()
{
return 'B';
}
有一個新的 class 模板來約束嗎? 沒問題,這個概念不需要額外的樣板就可以工作。
template <instantiation_of<D> T>
int Func()
{
return 'D';
}
OP寫道:
是的,如果可能的話,直接在函數模板參數中編寫一些“即時”代碼會很好......
通常,要確定它是否是某個給定 class 模板的特化,我們會提前定義一個特征,然后檢查該類型是否滿足該特征。 如果你不想提前定義任何東西,你必須找到一種方法來執行模板參數推導inline ,這樣你就可以檢查它是否成功。 在 C++20 中,這很簡單,但有點難看:
template <typename T>
void Func()
{
std::cout << "unconstrained" << std::endl;
}
template <typename T>
requires requires {
[]<typename U>(const A<U>&){}(std::declval<T>());
}
void Func()
{
std::cout << "constrained" << std::endl;
}
在這里, requires 子句檢查T
是否可以綁定到某個可推導出U
的const A<U>&
類型的參數。 你可以在這里看到這個例子: https://godbolt.org/z/dTEbaaPvh
這讀起來並不令人愉快。 如果您將多次使用此 hack,我認為最好只定義特征。 我回答你的問題只是為了滿足你的好奇心,而不是推薦這種技術。
上面的版本不僅會在模板參數是某個A<U>
時選擇受約束的版本,而且還會在它可能是 cv-qualified、可能是 ref-qualified 以及可能從A<U>
公開派生時選擇受約束的版本。 可以進行一些調整以使約束更加嚴格。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.