-
Notifications
You must be signed in to change notification settings - Fork 266
Description
I recently, thanks to awesome Jan 9th 2018 planet clang team work and others great articles, figured out how to configure my dev-setup to integrate llvm 7.0, visual studio 2017 15.5.6 for 32-bit and 64-bit Intel architecture.
My motivation for this was forced by Microsoft's 15.4.X breaking std lib framework changes that rendered the Microsoft experimental clang c2 front end (somewhat buggy anyway) to break.
In the Intel setup I use LLVM tools to both compile and link PDB debuggable Windows code.
See other posts I made on that topic for instructions on how to integrate everything so you can use latest updates to Visual Studio 2017 tools and debugging with latest 7.X builds of LLVM/clang. For those interested in full Windows 10 on ARM development (not UWP sillyness), I am separately still working the same setup for arm-32, arm-64 to all work together using LLVM tools as well as use Wine-ARM for Linux.
Once done with that integration, I was looking to see what LLVM 7.0 clang allowed to be done without needing P0289R0 Forward declarations of nested classes.
struct ds1; struct ds1::ds2;
I started fiddling around and wrote the sample below. It compiles and runs correctly with clang-llvm 7.0. It will not compile (without errors) when using Microsoft's latest c++ front-ends.
So, I scratched my head wondering if it is actually legal c++ code. I often do that, as I use c++ in non-standard style with templates and forward references. For example, I only use one cpp file per module and use includes within templates to minimize any forward declarations. That pattern avoids the need for makefiles and dramatically improves portability, compilation time, and often code generation quality. In effect, I use the .cpp file as a makefile with minimal to no macros and pure clang/gcc and c++ features.
In asking myself if the code was actually legit c++ according to the standard, I re-read through standard. I concluded that yes it was standard compliant to template rules, but that would make Microsoft's compiler be non-compliant. So I wondered if others more knowledgeable might chime in and clarify the question.
Here is the code sample:
(note it happens to also be intentionally infinitely recursive in a number of ways to test compiler detection)
// P0289R0 clang Forward declarations of nested classes
//- http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0289r0.pdf
// struct ds1; struct ds1::ds2;
struct nested1;
struct nested2;
// Code that references "nested1" here (could be pointer, but in template model this is more interesting case)
template <bool f_ta = true>
void foo(nested1& n1) {
n1.run();
}
template <bool f_ta = true>
struct outer {
struct inner {
void run() {
nested1 n1; nested2 n2;
n2.test();
foo(n1);
}
};
void test() {
nested1 n1;
foo(n1);
}
};
//using nested = outer::inner; // Must be defined at module-scope
//typedef outer::inner nested; // Must be defined at module-scope
struct nested1 : outer<>::inner { using super_t = outer<>::inner; using super_t::super_t; };
struct nested2 : outer<> { using super_t = outer<>; using super_t::super_t; };
bool fAutoRunIt = []() {
nested2 a;
a.test();
return true;
}();
You can easily modify the example to not be recursive and still test out the other forward reference behavior.
Cheers, David