Skip to main content
added 128 characters in body
Source Link
Incomputable
  • 9.6k
  • 3
  • 33
  • 72

Inheritance

I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.

Use cases

Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.

Too much runtime

If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.

Static way

Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.

template<class... Ts> struct overloaded : Ts... { 
    template <class... Fs> overloaded(Fs&&... fs) : 
        Ts{std::forward<Fs>(fs)}... 
    {}
    using Ts::operator()...; 
     
};
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

This requires C++17, but not hard to emulate using C++14, using make_overloaded.

Now, the usage:

    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); // v is std::variant

As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.

Inheritance

I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.

Use cases

Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.

Too much runtime

If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.

Static way

Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

This requires C++17, but not hard to emulate using C++14, using make_overloaded.

Now, the usage:

    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); // v is std::variant

As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.

Inheritance

I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.

Use cases

Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.

Too much runtime

If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.

Static way

Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.

template<class... Ts> struct overloaded : Ts... { 
    template <class... Fs> overloaded(Fs&&... fs) : 
        Ts{std::forward<Fs>(fs)}... 
    {}
    using Ts::operator()...; 
     
};
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

This requires C++17, but not hard to emulate using C++14, using make_overloaded.

Now, the usage:

    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); // v is std::variant

As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.

added 25 characters in body
Source Link
Incomputable
  • 9.6k
  • 3
  • 33
  • 72

Inheritance

I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory management,(and ownership semantics in general) and local variables are strongly typed.

Use cases

Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.

Too much runtime

If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.

Static way

Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

This requires C++17, but not hard to emulate using C++14, using make_overloaded.

Now, the usage:

    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); // v is std::variant

As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.

Inheritance

I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory management, and local variables are strongly typed.

Use cases

Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.

Too much runtime

If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.

Static way

Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

This requires C++17, but not hard to emulate using C++14, using make_overloaded.

Now, the usage:

    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); // v is std::variant

As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.

Inheritance

I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.

Use cases

Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.

Too much runtime

If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.

Static way

Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

This requires C++17, but not hard to emulate using C++14, using make_overloaded.

Now, the usage:

    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); // v is std::variant

As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.

Source Link
Incomputable
  • 9.6k
  • 3
  • 33
  • 72

Inheritance

I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory management, and local variables are strongly typed.

Use cases

Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.

Too much runtime

If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.

Static way

Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.

template<class... Ts> struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;

This requires C++17, but not hard to emulate using C++14, using make_overloaded.

Now, the usage:

    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); // v is std::variant

As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.