3 ms·
I don't think concepts are even necessary to do what pkolaczk wants to do, which is (I think) to constrain the argument to a particular interface, say Bar: t
by fauigerzigerk 11y ago
I don't think concepts are even necessary to do what pkolaczk wants to do, which is (I think) to constrain the argument to a particular interface, say Bar:
template <typename T>
void foo(const T& arg) {
const Bar* b = arg;
b->bar();
}
or
template <typename T>
void foo(const T& arg) {
static_assert(is_base_of<Bar, T>::value, "T must be a Bar");
arg.bar();
}
I can't say I'm a huge fan of either syntax, but the compiler will perform static type checking as if you had written where T : Bar in C#.
- pkolaczk 11y agoThe body of the template won't be typechecked until the instantiation of the template. This is different than in C#. If I replaced arg.bar with arg.baz in C#, the generic type definition would not compile, even if I never use it. In C++ I can't write a template and have it typechecked for all possible input types satisfying the type constraints, in C# I can. So C++ type system is weaker than that of C#.
- fauigerzigerk 11y agoI see what you mean, but uninstantiated also means unused. So we're not talking about anything that could possibly lead to runtime errors. It's not an issue with type safety. It definitely has a downside for the development process, especially when it comes to writing libraries. But it is also to some degree inevitable if you want structural typing. Maybe there is a better way to do it though.