簡體   English   中英

特定模板的模板 function 專業化(非類型)

[英]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是否可以綁定到某個可推導出Uconst A<U>&類型的參數。 你可以在這里看到這個例子: https://godbolt.org/z/dTEbaaPvh

這讀起來並不令人愉快。 如果您將多次使用此 hack,我認為最好只定義特征。 我回答你的問題只是為了滿足你的好奇心,而不是推薦這種技術。

上面的版本不僅會在模板參數是某個A<U>時選擇受約束的版本,而且還會在它可能是 cv-qualified、可能是 ref-qualified 以及可能從A<U>公開派生時選擇受約束的版本。 可以進行一些調整以使約束更加嚴格。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM