簡體   English   中英

帶有可變參數模板的靜態繼承

[英]Static inheritance with variadic templates

我正在嘗試使用std::conditional來實現靜態繼承。 我的child類有兩個可能的父類, parent_one ,它應該根據傳遞的類型保存多個變量,以及parent_two ,它需要兩種類型。 我正在使用標簽調度來區分我想要繼承的類。

現在到了問題。 當我調用child並將其標記為從parent_one繼承兩種類型時,它按預期工作。 但是,如果我嘗試將任意數量的類型傳遞給child並打算從parent_one繼承, parent_one出現錯誤:

static_polymorphism.cpp: In instantiation of ‘class child<foo_type, int, int, double, float>’:
static_polymorphism.cpp:110:41:   required from here
static_polymorphism.cpp:99:7: error: wrong number of template arguments (4, should be 2)
   99 | class child : public std::conditional_t<
      |       ^~~~~
static_polymorphism.cpp:90:7: note: provided for ‘template<class T, class F> class parent_two’
   90 | class parent_two {
      |       ^~~~~~~~~~
static_polymorphism.cpp: In function ‘int main(int, char**)’:
static_polymorphism.cpp:111:9: error: ‘class child<foo_type, int, int, double, float>’ has no member named ‘log’
  111 |   first.log();

如果我理解正確,編譯器應該根據我的標簽調度生成代碼。 這意味着它應該創建重載類 - N(基於傳遞的類型)來自parent_one和 M(基於傳遞的類型)來自parent_two 但是由於某種原因,我不知道,它不接受類型的變量計數。 你能告訴我我做錯了什么嗎?

實現就在這里。

using one_t = struct foo_type{};
using two_t = struct bar_type{};

template <typename ... TYPES>
class parent_one {
public:
  parent_one() = default;
  void log() {
    std::cout << "parent_one" << std::endl;
  }
};

template <typename T, typename F>
class parent_two {
public:
  parent_two() = default;
  void log() {
    std::cout << "parent_two" << std::endl;
  }
};

template <typename T, typename ... ARGS>
class child : public std::conditional_t<
    std::is_same_v<T, one_t>,
    parent_one<ARGS...>,
    parent_two<ARGS...>
  >
{
public:
  child() = default;
};

int main(int argc, char *argv[]) {
  child<one_t, int, int, double, float> first;
  first.log();

  child<two_t, int, int> second;
  second.log();
  return 0;
}

std::conditional_t<
    std::is_same_v<T, one_t>,
    parent_one<ARGS...>,
    parent_two<ARGS...>
>

在這里,在檢查條件之前驗證兩個備選方案。 std::conditional_t並不神奇,它只是一個常規模板,它需要所有模板參數都有效才能執行任何操作。

您需要延遲將模板參數替換到父模板中,直到選擇了其中一個選項之后。 這是一種可能的解決方案:

template <template <typename...> typename T>
struct delay
{
    template <typename ...P>
    using type = T<P...>;
};
// ...
class child :
    public std::conditional_t<
        std::is_same_v<T, one_t>,
        delay<parent_one>,
        delay<parent_two>
    >::template type<ARGS...> 
{
    // ...
};

你可能很經典:

template<class T, class... Args> struct child: parent_one<Args...> {};

template<class T, class A, class B> struct child<T, A, B>: parent_two<A, B> {};

template<class A, class B> struct child<one_t, A, B>: parent_one<A, B> {};

(這兩個特化可以通過requires (!std::is_same_v<T, one_t>)合並為一個)。

暫無
暫無

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

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