4 ms·
I'm absolutely aware of enable_if, type traits and SFINAE. But they do not address the concern I raised here. The things you mention come to play on template in
by pkolaczk 11y ago
I'm absolutely aware of enable_if, type traits and SFINAE. But they do not address the concern I raised here. The things you mention come to play on template instantiation, after the concrete (non-generic) types are already known.
The problem I mention is that with templates you cannot type check generic code. I can put whatever nonsense enable_ifs on my template declaration and the compiler does not check if they are satisfied by the implementation.
You can write the following C++ code and C++ allows it:
<template typename T>
void foo(const T& arg) { arg.bar(); }
This is perfectly fine for a macro system. But this is not how truly generic type system would work. If templates were proper generics, the typechecker would immediately refuse this to compile saying something like:
"Error: I can't prove T has the bar() member."
> C++ templates are Turing complete, you can validate whatever you feel like at compile time.
So please write a template metaprogram that validates if a given C++ class (input to the program, given as a template argument) matches a table schema in the database system (the table name and connection string are also given as template arguments). For fetching the schema, you have to connect to the DB, of course at compile time. If the schema does not match, the compilation should fail ;)
- pjmlp 11y agoBecause whoever wrote foo () was too lazy to make use of type traits and validate that T has a method called bar with zero arguments. Do you want an example how to write it properly? With or without the upcoming concepts TS already in GCC 6.0? Also this example would require T to be an interface with a bar method in C#. Do you also want to the the variant with MI and pure abstract classes in C+?
- pkolaczk 11y ago> Because whoever wrote foo () was too lazy to make use of type traits and validate that T has a method called bar with zero arguments. In a proper generic type system, the compiler validates it, not the programmer. Even if you constrain the type using type traits, the compiler would not check if the implementation satisfies the constraints. I can put a type trait for existence of bar() and then another programmer may rename bar() to baz() forgetting to update the constraint and the code will still compile fine.
- pjmlp 11y agoExcept that reasoning fails with concepts, already available in GCC 6.0 and as a TS.
- pkolaczk 11y agoSo you're saying concepts will reject libraries that compile fine today?
- pjmlp 11y agoThey might, if used properly. I do admit that I need to update myself with what GCC 6.0 allows vs the letter of the TS.
- fauigerzigerk 11y agoI 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 ago