簡體   English   中英

非專業模板類型對象的C ++列表?

[英]C++ list of unspecialized template type objects?

我一直在尋找有關此主題的問題,盡管也有類似的問題,但沒有一個能真正解決我的問題。 所以,我去。

假設我有一個模板類型F,並且我將一系列專門化聲明為另一個對象的成員變量:

F<A> a;
F<B> b;
.
.
.

稍后,我想遍歷這些對象並執行在任何F實例上定義的操作。

因此,我的沖動是創建一個std :: list <F>,但這不起作用。

有沒有一種方法可以創建類型為F的對象的列表,即不指定template參數呢?

我的預感不是,不是C ++,但是希望我錯了。

不幸的是,答案是否定的 在C ++中,您不能擁有一個異構的不相關對象的容器,並且同一模板的不同實例是不相關的。

使其起作用的唯一方法是使用某種形式的類型擦除。 最慣用的方法是使用繼承和虛函數,並將指向基礎對象的指針放入列表中。

就C ++而言,模板類或結構的兩個不同模板實例是完全獨立的類型,彼此之間沒有任何關系。 例如, std::vector<int>std::vector<char>是單獨的類型; 兩者都不來自對方或任何共同基礎。 兩種類型都來自同一模板的實例化這一事實並沒有在這些類型之間創建語義關系。 從這種意義上(並且這種意義上),您可能會想到諸如預處理器宏之類的模板,這些模板在編譯前已擴展為聲明新的無關類型。

但是,您可以使用繼承自行創建這樣的關系,就像使用任何非模板類型一樣:

#include <iostream>

struct foo_base {
    virtual void print() = 0;
};

template <typename T>
struct foo : foo_base {
    foo(T data) : data(data) {}
    virtual void print() override {
        std::cout << data << std::endl;
    }
    private: T data;
};

void example() {
    foo<int> f(42);
    f.print();
}

在這里, foo<int>foo<char>是單獨的類型(作為foo<>模板的不同實例化),但是所有foo<>實例化都源自foo_base (當然,除非您提供foo<>的顯式特化,它不是foo_base派生的...)

除非所有F<X>都獨立於某個獨立於X公共基類派生,否則只有使用類型擦除或異構容器才有可能實現。

如果它們都繼承自Foo ,那么您當然可以將它們作為Foo& / Foo*進行迭代,但是我想您知道這一點。

如果它們的類型不同,則標准容器無法容納它們,因為它們是同質的-所有元素都具有相同的類型。 可能有一些帶有異構容器的庫,但是在STL中,您只能使用std::variantstd::any來模仿。

最后一個辦法,我能想象這工作了-我不建議這一點-是通過創建封裝類的派生類的F<X> S(可變參數模板)和編碼調用轉換成層次結構,ST每˚F s foo`被稱為

由於涉及到更多,這里是一個示例:

#include <iostream>

template <class X>
class Foo {
    X mem;
    public:
    explicit Foo(X arg) : mem(arg) {}
    void foo() {
        std::cout << mem;
    }
};

template <class X, class ...Xs> class Holder;

template <class X>
class Holder<X> {
    X member;
    public:
    Holder(X arg) : member(std::forward<decltype(arg)>(arg)) {}
    void call() {
        member.foo();
    }
};

template <class X, class ...Ys>
class Holder : public Holder<Ys...> {
    X member;
    public:
    Holder(X arg, Ys ...args) : Holder<Ys...>(std::forward<decltype(args)>(args)...), member(std::forward<decltype(arg)>(arg)) { }

    void call() {
        member.foo();
        Holder<Ys...>::call();
    }
};

int main() {
   // omitting the template-args requires c++17 deduction guides
    Holder holder(Foo(4), Foo(" Hello "), Foo(7L), Foo(" World "));
    holder.call();
    std::cout << std::endl;
}

您也許可以猜測,這通常不是您想要的,因為它非常復雜。 實際上,我省略了一些事情,例如完美地傳遞參數以將其保持在最小限度,希望有人可以理解這個概念。

暫無
暫無

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

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