6 Replies - 960 Views - Last Post: 08 October 2017 - 11:49 AM

#1 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 5922
  • View blog
  • Posts: 20,246
  • Joined: 05-May 12

std::visit is everything wrong with modern C++

Posted 14 September 2017 - 06:53 PM

Interesting blog post...

std::visit is everything wrong with modern C++

Quote

To paraphrase Meyers, Iím sure each member of the committee cares very much about avoiding needless complexity and making the language easier to use. But if you look at the results of their work, itís hard to tell. The accidental complexity just keeps stacking up.


Is This A Good Question/Topic? 0
  • +

Replies To: std::visit is everything wrong with modern C++

#2 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: std::visit is everything wrong with modern C++

Posted 15 September 2017 - 08:57 AM

I'm not sure I follow the author's criticism here. I mean sure, I'd greatly prefer pattern matching as a language feature over having to use the visitor pattern, but I don't think that was the author's main point.

Quote

itís completely bonkers to expect the average user to build an overloaded callable object with recursive templates just to see if the thing theyíre looking at holds an int or a string.


Yes, that would be completely bonkers, but that's a straw man. You don't need recursive templates to check whether a variant is an int or a string. All you need is a visitor class with two operator()s. The recursive templates are only needed to implement the lambda shortcut (and only if you want to implement it as generically as possible), which was the author's own bonkers idea.

And yes, the visitor pattern can be verbose, but it's not only more verbose in C++17 than it was in previous C++ versions or than it is in, say, Java.
Was This Post Helpful? 0
  • +
  • -

#3 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 5922
  • View blog
  • Posts: 20,246
  • Joined: 05-May 12

Re: std::visit is everything wrong with modern C++

Posted 15 September 2017 - 01:05 PM

View Postsepp2k, on 15 September 2017 - 11:57 AM, said:

You don't need recursive templates to check whether a variant is an int or a string. All you need is a visitor class with two operator()s.


That's the "boilerplate code" option:

Quote

To accomplish this meager mission, we had to:

Define a function object, which requires a lot of boilerplate


Perhaps as C++ programmers, we are so used to seeing/writing boilerplate code that we are immune to it, but imagine people whose primary language is not C++, but Java or C#. For example, in I only need to write the function definition once in C# or Java. In C++, to write good clean code, I write a header file that has the function declarations, and then in the implementation file(s), I write the function definitions which repeats a lot of the same information that was in the header file. Another example of boilerplate code in C++ is the rule of three/five. We just take it for granted or the consider it the cost of doing business. It's like "You use an iPhone? Of course, you need to have iTunes."
Was This Post Helpful? 0
  • +
  • -

#4 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: std::visit is everything wrong with modern C++

Posted 15 September 2017 - 01:18 PM

View PostSkydiver, on 15 September 2017 - 10:05 PM, said:

That's the "boilerplate code" option:

Quote

To accomplish this meager mission, we had to:

Define a function object, which requires a lot of boilerplate


But that's the normal way to define visitors. And I wouldn't consider defining a class with two member functions that much overhead. I mean, yes, it sucks compared to pattern matching, but it's not any more unwieldy than in other OO languages, so I don't see why the author argues that that's what's wrong with C++17.

Quote

Perhaps as C++ programmers, we are so used to seeing/writing boilerplate code that we are immune to it, but imagine people whose primary language is not C++, but Java or C#.


But the visitor pattern looks exactly the same in those languages.

Quote

For example, in I only need to write the function definition once in C# or Java. In C++, to write good clean code, I write a header file that has the function declarations, and then in the implementation file(s), I write the function definitions which repeats a lot of the same information that was in the header file.


That's certainly an annoyance in general, but I don't think you really need to put your visitor classes in headers in most use cases. That is, I don't think you'd commonly need to use the class in more than one place, so you'd just define it in the c++ file where you use it.

Quote

Another example of boilerplate code in C++ is the rule of three/five. We just take it for granted or the consider it the cost of doing business.


Okay, but now we're no longer talking about std::visit, right? At least I don't see the connection.
Was This Post Helpful? 0
  • +
  • -

#5 Skydiver  Icon User is offline

  • Code herder
  • member icon

Reputation: 5922
  • View blog
  • Posts: 20,246
  • Joined: 05-May 12

Re: std::visit is everything wrong with modern C++

Posted 15 September 2017 - 08:09 PM

The connection I was trying to point out was that as C++ programmers, we have gotten so used to seeing and writing boilerplate code.

My reading of the author's post that he was pointing out that the newer features in C++ seem to require more and more complexity.
Was This Post Helpful? 0
  • +
  • -

#6 sepp2k  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 2517
  • View blog
  • Posts: 4,001
  • Joined: 21-June 11

Re: std::visit is everything wrong with modern C++

Posted 16 September 2017 - 02:55 AM

View PostSkydiver, on 16 September 2017 - 05:09 AM, said:

The connection I was trying to point out was that as C++ programmers, we have gotten so used to seeing and writing boilerplate code.


But again that implies that using visit in C++ requires more boilerplate than doing the equivalent in Java or C# or else all the Java and C# who aren't used to as much boilerplate would be complaining in droves about how complicated the visitor pattern is in their languages, right?

Quote

My reading of the author's post that he was pointing out that the newer features in C++ seem to require more and more complexity.


I got that, but I don't see how std::visit is an example of that. If anything implementing the visitor pattern using std::visit is less complex and boilerplaty than doing it in previous versions of C++ (or Java or C#) since the core of the pattern is now built-in.

Maybe my point becomes clearer if I talk in actual code. So let's take the example of a value type that represents values in some DSL (like ini files in the author's example) and implement it in Java, C++ (without boost or C++17 features) and C++17 to compare the complexity and boiler plate.

Java:

interface Value {
    public abstract void accept(ValueVisitor v);
}

class StringValue implements Value {
    private String value;
    // insert constructor and getter here
    public void accept(ValueVisitor v) {
        v.visit(this);
    }
}

class IntValue implements Value { /* same as for StringValue except with int instead of String*/ }

// insert classes for other supported types here

interface ValueVisitor {
    public static void applyVisitor(ValueVisitor visitor, Value value) { value.accept(visitor); }
    public void visit(StringValue s);
    public void visit(IntValue i);
    // insert methods for other types here
}

class DoSomething implements ValueVisitor {
    public void visit(StringValue s) {
        doSomethingWithString(s.getString());
    }

    public void visit(IntValue i) {
        doSomethingElseWithInt(i.getInt());
    }
}

// Usage: ValueVisitor.applyVisitor(new DoSomething(), myValue);



C++:


class ValueVisitor;

class Value {
public:
    virtual void accept(ValueVisitor& v) = 0;
}

// insert classes for other supported types here

class ValueVisitor {
public:
    void operator()(StringValue& s);
    void operator()(IntValue& i);
    // insert methods for other types here
}

void applyVisitor(ValueVisitor& visitor, Value& value) {
    value.accept(visitor);
}

class StringValue : public Value {
    std::string value;
public:
    // insert constructor and getter here
    void accept(ValueVisitor& v) {
        v(this);
    }
}

class IntValue : public Value { /* same as for StringValue except with int instead of String*/ }

class DoSomething : public ValueVisitor {
public:
    void visit(StringValue& s) {
        doSomethingWithString(s.getString());
    }

    public void visit(IntValue& i) {
        doSomethingElseWithInt(i.getInt());
    }
}

// Usage: DoSomething ds; applyVisitor(ds, myValue);



C++17 (or previous versions with boost):

using Value = std::variant<std::string, int /*, insert other types here */>;

class DoSomething {
public:
    void operator()(StringValue& s) {
        doSomethingWithString(s.getString());
    }

    void operator()(IntValue& i) {
        doSomethingElseWithInt(i.getInt());
    }
}

// Usage: DoSomething ds; std::visit(ds, myValue);



And lastly let's look at the same thing in ML to have a non-OO example in there:

type Value = StringValue of string | IntValue of int (* | insert other types here *)

let doSomething value =
  match value with
  | StringValue s -> doSomethingWithString s
  | IntValue i -> doSomethingElseWithInt i

(* Usage: doSomething myValue *)



So, in my opinion, the ML version is the clear winner here, but as far as the OO languages go, the C++17 version is a clear step up from the old C++ version or the Java version (which are pretty much equivalent).

So I don't see how that's an example of over-complicating the language. It may be an example of not simplifying the language enough, but I'm sure if C++17 did introduce ML-like pattern matching someone would be complaining that they over-complicated the language by introducing these obscure functional features that nobody needs.

PS: It's not like I agree with the statement that C++ is being over-complicated in general. I just don't see how this is an example of that.
Was This Post Helpful? 1
  • +
  • -

#7 snoopy11  Icon User is offline

  • Engineering ● Software
  • member icon

Reputation: 1392
  • View blog
  • Posts: 4,396
  • Joined: 20-March 10

Re: std::visit is everything wrong with modern C++

Posted 08 October 2017 - 11:49 AM

The new parts of C++ are too complex IMO,

I agree with the Author how do you teach this ?

If you cant teach it, is it worth having as part of the language.

The growing complexity of C++ is a problem, new code should be simplifying coding problems not obscuring them.

My two cents.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1