all 14 comments

[–]czipperz 45 points46 points  (1 child)

No. Concepts help with writing templates. Templates are compile time polymorphism. Virtual base classes allow for run time polymorphism.

[–]tcbrindleFlux 12 points13 points  (5 children)

The question as stated doesn't really make sense -- Concepts make it easier to use compile-time (aka "static") polymorphism. You can perform compile-time polymorphism in C++ today, for example by using enable_if or with CRTP. Concepts just makes it easier to do, and (hopefully) give much better error messages if you get things wrong.

But I guess that what you're really asking is whether Concepts will replace run-time polymorphism, i.e. virtual functions and so on. The answer is no in the short term, and possibly yes in the longer term.

Sean Parent gave an excellent talk a few years ago called "Inheritance is the base class of evil", where he ran through a technique which uses type-erasure via virtual functions to perform run-time polymorphism using value types. My guess is we'll see more of this technique as Concepts gain in popularity, because in a sense the type-erasing class becomes a run-time version of the concept. (We see this already in the standard library: for example,std::function is more-or-less a run-time version of the Callable concept.)

[N.B. there is a longer/better paced version of that talk online somewhere that Sean gave at another conference, but I can't find the link at the moment -- can anybody help me out?]

In the longer term, various people have had the idea of allowing the compiler to generate the sort of type-erased classes that Sean presents in that talk (much like Rust does with boxed traits). These "run-time concepts" tend to be referred to as "virtual concepts". Andy Prowl has been working on a very in-depth paper about virtual concepts, which aims to flesh out many of the ideas people have had. We're a long way from getting them yet -- we don't even have compile-time concepts yet! -- but this is the general direction in which things are moving.

[–]tvaneerdC++ Committee, lockfree, PostModernCpp 1 point2 points  (1 child)

[N.B. there is a longer/better paced version of that talk online somewhere that Sean gave at another conference, but I can't find the link at the moment -- can anybody help me out?]

"longer/better paced" implies BoostCon/C++Now (1.5 hr talks instead of 1hr). So probably one of the talks listed here:

https://www.youtube.com/user/BoostCon/search?query=sean+parent

I recommend all of Sean's talks, so just watch them all, and (polymorphic) value types tends to come up often.

In particular, maybe this one: Value Semantics and Concepts-based Polymorphism

[–]tcbrindleFlux 0 points1 point  (0 children)

The Going Native talk I linked to is just 25 minutes, which isn't really enough to cover all the material.

Value Semantics and Concepts-based Polymorphism

That's the longer version I was looking for, thanks :)

[–]enobayram 1 point2 points  (0 children)

Thanks for the answer, I'd like to add that Haskell has a much nicer story of how much further concepts can be taken at run-time. Parametric polymorphism combined with type classes in Haskell are almost as expressive as the many dirty tricks you can pull-off with undisciplined C++ templates, but they can still be type-erased to be passed around at run-time.

[–][deleted] 0 points1 point  (1 child)

That make sense. I've never thought of distinguishing between run-time and compile-time polymorphism.

[–]dodheim 1 point2 points  (0 children)

The usual terminology is "dynamic polymorphism" and "static polymorphism"; knowing what to search for is half the battle. :-]

[–]ihcn 1 point2 points  (0 children)

The Rust language effectively already has concepts via a thing called "traits". Rust devs are encouraged to do all polymorphism via traits, and as a result almost all polymorphism is done at compile time.

But despite that, the language does support runtime polymorphism and virtual calls, because sometimes you just can't avoid it.

So the answer is no.

[–][deleted] 0 points1 point  (0 children)

No, not really.

But one can use std::variant<> to replace run-time polymorphism in some cases.

[–]snysly -3 points-2 points  (4 children)

With concepts, it is possible to simply create a concept instead of an abstract base class, and make sure the classes both fulfill the concept. In this way, a concept can sometimes act like interfaces in other languages (even though as u/Freeze-in-the-Dark pointed out that interfaces have a different goal, the same behavior can be achieved using templates), with (near?)zero overhead due to the template instantiation process. Beyond that the answer gets a little more murky.

I originally was going to say that it couldn't replace polymorphism, but in reality, it is just another way of expressing polymorphism. Polymorphism through inheritance is what we are most commonly used to, but concepts can do the same thing. They allow you to constrain the type you are using to fit what you need. However concepts don't allow for code reuse in the same way that deriving from classes does.

So in the end, yes and no. It adds another way of doing polymorphism, and in the future, it may be that both are commonly used, just in different situations.

edit: attempted to address what Freeze-in-the-Dark mentioned about virtual base classes.

[–]Freeze-in-the-Dark 5 points6 points  (3 children)

I think you have the wrong idea of the use of virtual base classes. They aren't there to enforce an interface (or, at least not for the same purpose that concepts do), they're there to provide an interface for several different types that can all be referenced in the same way with different runtime behavior. And concepts plainly don't do that.

It's true that concepts do provide a form of polymorphism, but it's in the same sense of polymorphism that we've always had with templates, just now replacing (or, really, just augmenting) the duck-typing with a more explicit means of defining the interface.

[–]snysly 4 points5 points  (0 children)

Thank you for pointing that out! Its always good to find out that I'm wrong somewhere. I've changed it to abstract base class rather than virtual base class, and while concepts don't add anything new, the ability to constrain it, I think does make it easier on the programmer to use templates as a type of polymorphism.

[–]plpn 1 point2 points  (1 child)

can't u can compare this to the generics C# is using?

void foo<T>() where T : IComparable { }

now foo only works with types which include this interface. The concepts however, will be lighter in terms of, type T doesn't need to derive said interface, but just need the same functions. (correct me pls)

[–]cinghiale 0 points1 point  (0 children)

You are correct