簡體   English   中英

C++ 高階模板

[英]C++ Higher order templates

我正在嘗試在 C++ 中創建一個系統,在那里我可以實現許多不同的實體 E,每個實體都具有與之關聯的不同類型 T。 我想為這些創建一個通用所有者,以便對於與 T1 相關聯的 E1、與 T2 相關聯的 E2 等實現,我可以將它們包裝在一個容器中,在那里它們都可以被管理,就像(在偽代碼中)

E<ConcreteT1> e1;
E<ConcreteT2> e2;
//...
Container c;
c.add(e1)
c.add(e2)
//...

我是 C++ 的初學者,我知道基本模板,但我認為我需要某種“高階模板”,其中頂層 (C) 是通用的,而中間層 (E) 又是通用的在隨后的水平。 也許這是一個完全的反模式,我做錯了。 請讓我知道如何解決這個問題。 我很高興使用 C++17 功能,但如果可能的話,我寧願避免使用最新最好的 C++20。

謝謝

編輯:我要解決的實際問題是在某些方法中具有一個采用通用 E (事件)的接口。

template <typename E>
class Interface{
  method(E e){...}
}

我想實現許多混凝土(事件處理程序),每個都有自己的 E(事件類型)

class EOne{}
class ImplOne:Interface<EOne>{
  method(Eone e){...}
}

class ETwo{}
class ImplTwo:Interface<ETwo>{
  method(ETwo e){...}
}

然后在更多的容器中管理這些,比如上面的Container c 然后我將有一個可調用對象隊列,其中可調用對象可以使用相應的事件類型調用 methodN。


for(auto &handler:container){
 eventQueue.pop()();
}

我知道我可能在這里走錯了路。

您可以使用std::variant並使用訪問。

例如。 隊列 object 可以定義為

using InterfaceVar = std::variant<Interface<E1>, Interface<E2>>;
std::queue< InterfaceVar > eventQueue;

然后你會使用訪問來區分類型(聽起來你想要這樣)。 您可以為此使用std::visit或您自己的訪問方法。

來自 cppreference 的示例

#include <iomanip>
#include <iostream>
#include <string>
#include <type_traits>
#include <variant>
#include <vector>
 
// the variant to visit
using var_t = std::variant<int, long, double, std::string>;
 
// helper constant for the visitor #3
template<class> inline constexpr bool always_false_v = false;
 
// helper type for the visitor #4
template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
// explicit deduction guide (not needed as of C++20)
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;
 
int main() {
    std::vector<var_t> vec = {10, 15l, 1.5, "hello"};
    for(auto& v: vec) {
 
        // 1. void visitor, only called for side-effects (here, for I/O)
        std::visit([](auto&& arg){std::cout << arg;}, v);
 
        // 2. value-returning visitor, demonstrates the idiom of returning another variant
        var_t w = std::visit([](auto&& arg) -> var_t {return arg + arg;}, v);
 
        // 3. type-matching visitor: a lambda that handles each type differently
        std::cout << ". After doubling, variant holds ";
        std::visit([](auto&& arg) {
            using T = std::decay_t<decltype(arg)>;
            if constexpr (std::is_same_v<T, int>)
                std::cout << "int with value " << arg << '\n';
            else if constexpr (std::is_same_v<T, long>)
                std::cout << "long with value " << arg << '\n';
            else if constexpr (std::is_same_v<T, double>)
                std::cout << "double with value " << arg << '\n';
            else if constexpr (std::is_same_v<T, std::string>)
                std::cout << "std::string with value " << std::quoted(arg) << '\n';
            else 
                static_assert(always_false_v<T>, "non-exhaustive visitor!");
        }, w);
    }
 
    for (auto& v: vec) {
        // 4. another type-matching visitor: a class with 3 overloaded operator()'s
        std::visit(overloaded {
            [](auto arg) { std::cout << arg << ' '; },
            [](double arg) { std::cout << std::fixed << arg << ' '; },
            [](const std::string& arg) { std::cout << std::quoted(arg) << ' '; },
        }, v);
    }
}

暫無
暫無

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

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