簡體   English   中英

C ++:將模板的類型參數部分專門化為另一個模板類的成員類型

[英]C++: Partially specializing template's type parameter as another template class's member-type

我有一個模板結構SFoo ,其中包含成員struct SZug

template <typename tTYPE>
struct SFoo
  {
    struct SZug {};
  };

我還有另一個帶有類型參數的struct SBar

template <typename tTYPE>
struct SBar
  { /* stuff */ };

我想專門SBar使用SZug的類型參數,如下所示:

template <typename tTYPE>
struct SBar<typename SFoo<tTYPE>::SZug>
  { /* different stuff */ };

這不會編譯-LLVM輸出:

不可推導模板參數'tTYPE'

盡管編譯器可以根據需要輕松推斷出這種情況,但我猜測這只是C ++規范需要專門涵蓋這種情況。

有什么辦法可以做到這一點?
(注:我目前工作圍繞它通過移動SZug之外SFoo和使用using聲明,但它是丑陋的。)

我不確定我是否完全了解您想要做什么,但是您可以嘗試以下操作(它只需要向SZug添加特定屬性:

template <typename tTYPE>
struct SFoo {
    struct SZug {
        // Add this to be able to obtain SFoo<T> from SFoo<T>::SZug
        using type = tTYPE;
    };
};

然后是一個小模板,用於檢查類型是否為SFoo<T>::SZug

template <typename tTYPE, typename Enabler = void>
struct is_SZug: public std::false_type { };

template <typename tTYPE>
struct is_SZug<tTYPE, typename std::enable_if<
  std::is_same<tTYPE, typename SFoo<typename tTYPE::type>::SZug>{}
>::type>: public std::true_type { };

如果類型是SZug ,則對SBar模板進行略微修改以啟用“專業化”:

template <typename tTYPE, typename Enabler = void>
struct SBar
  { static void g(); };

template <typename tTYPE>
struct SBar<tTYPE, typename std::enable_if<is_SZug<tTYPE>{}>::type>
  { static void f(); };

一點檢查:

void f () {
  SBar<int>::g();
  SBar<SFoo<int>::SZug>::f();
}

注意:您也可以直接將SFoo<T>設置為SFoo<T>::SZugtype屬性,您只需要稍微更改std::is_same的第二個參數std::is_same

您可以通過以下方式獲得想要的效果 (打印出0 1,BTW):

#include <type_traits>
#include <iostream>

namespace detail
{   
    struct SZugBase{};
}   

template <typename tTYPE>
struct SFoo                                                                                                                                
{   
    struct SZug : public detail::SZugBase {}; 
};  

template<typename tType, bool IsFoo>
struct SBarBase
{   
    int value = 0;
};  

template<typename tType>
struct SBarBase<tType, true>
{   
    int value = 1;
};  

template <typename tTYPE>
struct SBar : public SBarBase<tTYPE, std::is_convertible<tTYPE, detail::SZugBase>::value>
{ /* stuff */ };

int main()
{   
    SBar<int> b0; 
    SBar<SFoo<int>::SZug> b1; 

    std::cout << b0.value << " " << b1.value << std::endl;
}   

說明

首先,我們為SZug提供常規課程:

namespace detail
{   
    struct SZugBase{};
}   

template <typename tTYPE>
struct SFoo                                               
{   
    struct SZug : public detail::SZugBase {}; 
};  

請注意以下幾點:

  1. SZugBase沒有任何參數,因此很容易獨立於SFoo的參數進行SFoo

  2. SZugBase位於detail名稱空間中,因此,按照通用的C ++約定,您要告訴客戶端代碼將其忽略。

現在,我們為SBar兩個基類,專門針對某些東西是否可轉換為SZug的非模板基:

template<typename tType, bool IsFoo>
struct SBarBase
{   
    int value = 0;
};  

template<typename tType>
struct SBarBase<tType, true>
{   
    int value = 1;
};  

最后,我們只需要使SBar成為這些基礎的子類(取決於專業化):

template <typename tTYPE>
struct SBar : public SBarBase<tTYPE, std::is_convertible<tTYPE, detail::SZugBase>::value>
{ /* stuff */ };

請注意,您在這里不專門研究SBar ,而是專門研究基類。 但是,這有效地產生了相同的效果。

暫無
暫無

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

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