Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

>I suppose it depends on how much faith you place in the foresight of whoever is writing the template as well as their vigilance :P

The actual effects depend on a lot of things. I'm just saying, it seems contrived to me, and the most likely outcome of this type of broken template is failed compilation.

>As a fun (?) bit of trivia that is only tangentially related: one benefit of definition-site checking is that it can allow templates to be separately compiled.

This is incompatible with how C++ templates work. There are methods to separately compile much of a template. If concepts could be made into concrete classes and used without direct inheritance, it might work. But this would require runtime concepts checking I think. I've never tried to dynamic_cast to a concepts type, but that would essentially be required to do it well. In practice, you can still do this without concepts by making mixins and concrete classes. It kinda sucks to have to use more inheritance sometimes, but I think one can easily design a program to avoid these problems.

>I believe you can't avoid it in C++ without pretty significant backwards compatibility questions/issues. It's part of the reason that feature was dropped from the original concepts design.

This sounds wrong to me. Template parameters plus template code actually turns into real code. Until you actually pass in some concrete parameters to instantiate, you can't test anything. That's what I mean by saying it's "unavoidable". No language I can dream of that has generics could do any different.

>Not always, I think? For example, if you accidentally assume the presence of a copy constructor/assignment operator and someone else later tries to use your template with a non-copyable type it may not be realistic for the user to change their type to make it work with your template.

I wasn't prescribing a fix. I was describing a new type of error that can't be detected automatically (and which it would not be reasonable for a language to try to detect). If the template requires `foo()` and you just create an empty function that does not satisfy the semantic intent of the thing, you will make something compile but may not actually make it work.





> I'm just saying, it seems contrived to me

Sure. Contrivance is in the eye of the beholder for this kind of thing, I think.

> and the most likely outcome of this type of broken template is failed compilation.

I don't think that was ever in question? It's "just" a matter of when/where said failure occurs.

> This is incompatible with how C++ templates work.

Right, hence "tangentially related". I didn't mean to imply that the aside is applicable to C++ templates, even if it could hypothetically be. Just thought it was a neat capability.

> This sounds wrong to me.

Wrong how? Definition checking was undeniably part of the original C++0x concepts proposal [0]. As for some reasons for its later removal, from Stroustrup [1]:

> [W]e very deliberately decided not to include [template definition checking using concepts] in the initial concept design:

> [Snip of other points weighing against adding definition checking]

> By checking definitions, we would complicate transition from older, unconstrained code to concept-based templates.

> [Snip of one more point]

> The last two points are crucial:

> A typical template calls other templates in its implementation. Unless a template using concepts can call a template from a library that does not, a library with the concepts cannot use an older library before that library has been modernized. That’s a serious problem, especially when the two libraries are developed, maintained, and used by more than one organization. Gradual adoption of concepts is essential in many code bases.

And Andrew Sutton [2]:

> The design for C++20 is the full design. Part of that design was to ensure that definition checking could be added later, which we did. There was never a guarantee that definition checking would be added later.

> To do that, you would need to bring a paper to EWG and convince that group that it's the right thing to do, despite all the ways it's going to break existing code, hurt migration to constrained templates, and make generic programming even more difficult.

I probably could have used a more precise term than "backwards compatibility", to be fair.

> Until you actually pass in some concrete parameters to instantiate, you can't test anything. That's what I mean by saying it's "unavoidable".

I'm a bit worried I'm misunderstanding you here? It's true that C++ as it is now requires you to instantiate templates to test anything, but what I was trying to say is that changing the language to avoid that requirement runs into migration/backwards compatibility concerns.

> No language I can dream of that has generics could do any different.

I've mentioned Swift and Rust already as languages with generics and definition-site checking. C# is another example, I believe. Do those not count?

> I wasn't prescribing a fix. I was describing a new type of error that can't be detected automatically (and which it would not be reasonable for a language to try to detect). If the template requires `foo()` and you just create an empty function that does not satisfy the semantic intent of the thing, you will make something compile but may not actually make it work.

My apologies for the misdirected focus.

In any case, that type of error might be "new" in the context of the conversation so far, but it's not "new" in the PL sense since that's basically Rice's theorem in a nutshell. No real way around it beyond lifting semantics into syntax, which of course comes with its own tradeoffs.

[0]: https://isocpp.org/wiki/faq/cpp0x-concepts-history#cpp0x-con...

[1]: https://www.stroustrup.com/good_concepts.pdf

[2]: https://old.reddit.com/r/cpp/comments/cx141j/c20_concepts_an...


That is all very good information. I don't often get into the standards and discussions about the stuff. Maybe ChatGPT or something can help me find interesting topics like this one but it hasn't come up so much for me yet.

>I'm a bit worried I'm misunderstanding you here? It's true that C++ as it is now requires you to instantiate templates to test anything, but what I was trying to say is that changing the language to avoid that requirement runs into migration/backwards compatibility concerns.

I see now. I could imagine a world where templates are compiled separately and there is essentially duck typing built into the runtime. For example, if the template parameter type is a concept, your type could be automatically hooked up as if it was just a normal class and you inherited from it. If we had reflection, I think this could also be worked out at compile time somehow. But I'm not very up to speed with what has been tried in this space. I'm guessing that concept definitions can be very extensive and also depend on complex expressions. That sounds hairy compared to what could be done without concepts, for example with an abstract class.


> I could imagine a world where templates are compiled separately and there is essentially duck typing built into the runtime.

The bit of my comment you quoted was just talking about definition checking. Separate compilation of templates is a distinct concern and would be an entirely new can of worms. I'm not sure if separate compilation of templates as they currently are is possible at all; at least off the top of my head there would need to be some kind of tradeoff/restriction added (opting into runtime polymorphism, restricting the types that can be used for instantiation, etc.).

I think both definition checking and separate compilation would be interesting to explore, but I suspect backwards compat and/or migration difficulties would make it hard, if not impossible, to add either feature to standard C++.

> For example, if the template parameter type is a concept, your type could be automatically hooked up as if it was just a normal class and you inherited from it.

Sounds a bit like `dyn Trait` from Rust or one of the myriad type erasure polymorphism libraries in C++ (Folly.Poly [0], Proxy [1], etc.). Not saying those are precisely on point, though; just thought some of the ideas were similar.

[0]: https://github.com/facebook/folly/blob/main/folly/docs/Poly....

[1]: https://github.com/microsoft/proxy




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: