簡體   English   中英

訪問者模式中的完美轉發 std::visit of C++

[英]Perfect forwarding in the visitor pattern std::visit of C++

我每周都在看 Jason Turner C++,我看到了這個代碼片段。

template<typename... B>
struct Visitor: B...{

template<typename... T>
Visitor(T&&...t): B(std::forward<T>(t))...{} 

using B::operator()...;
};

template<typename...T>
Visitor(T...) -> Visitor<std::decay_t<T>...>;

int main(){
    std::array<std::variant<double, int, std::string>, 6> a{3.2, 2, 4, 6, 2.4, "foo"};
    int intTotal = 0;
    double doubleTotal = 0.0;

    Visitor visitor {[&intTotal](const int i){intTotal += i;},
                  [&doubleTotal](const double d) { doubleTotal += d;},
                 [](const std::string& c) { }};

    std::for_each(begin(a), end(a), [&visitor](const auto &v) {std::visit(visitor, v);});
    std::cout << intTotal << " " << doubleTotal << std::endl;
}

我可以擺脫完美轉發以及推導指南。 這算不算C++中的最佳實踐,在什么情況下效率比較低?

template<typename... B>
struct Visitor: B...{

  Visitor(const B&... b): B(b)... { }
  using B::operator()...;
};

電子

我可以擺脫完美轉發

通過 const 引用傳遞將復制 lambdas 而不是移動它們。

在您的情況下這無關緊要,但 lambda 是否按價值捕獲事物會很重要。 如果 lambda 的復制成本很高,可能會損害性能,或者如果無法復制 lambda 會導致編譯錯誤(因為它們具有不可復制的 state,例如[x = std::make_unique<int>()](){} )。

我可以擺脫...演繹指南。

如果你通過 const 引用,是的。 但是,如果您通過轉發參考,則不會。

具有一組獨立模板參數的構造函數是一個問題。 Buf 如果您使用相同的模板參數(並且繼承自std::decay_t<B>... ),它仍然無法正常工作,因為內置的推導指南拒絕進行完美轉發。 如果您傳遞了一個左值,則模板參數推導將不起作用。


一個更好的問題是為什么要有一個構造函數。 如果刪除它,該類型將變為聚合,並且一切都將像以前一樣繼續工作。

它甚至可以讓您刪除推導指南(除了 Clang 尚不支持)。

Visitor(const B&... b)

這個構造函數的所有參數現在都將是const引用......

                        : B(b)... 

...如果這些子類的構造函數中的任何一個采用非const引用的相應參數,則這將是格式錯誤的並且無法編譯。

class Foo {

public:
    Foo(int &n) {}
};

嘗試使用您的訪客與此 class,看看它是否有效。 您的模板實例的構造函數應該類似於

Visitor(const int &n) : Foo(n) {}

暫無
暫無

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

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