Created
August 31, 2015 15:14
-
-
Save RossBencina/157eecf2189739cd913f to your computer and use it in GitHub Desktop.
Experiment: Inheriting Types From Template Base Class
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Inheriting Types From Template Base Class | |
/// ========================================= | |
/// | |
/// I put together this comparison of various methods of looking up types in | |
/// a base class template after noticing that my code would compile correctly | |
/// in MSVC but break in clang and gcc. | |
/// | |
/// Having reviewed the various cases, my conclusion is that MSVC is very | |
/// permissive in looking up names in base class templates. It doesn't | |
/// implement the correct C++ dependent name lookup rules. | |
/// | |
/// For more information on how dependent name lookup works in C++ | |
/// see the first answer here: | |
/// * http://stackoverflow.com/questions/19816509/use-typedef-using-from-templated-base-class-in-derived-class | |
/// Also: | |
/// * https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-members | |
/// * http://stackoverflow.com/questions/3758656/c-template-inheritance-issue-with-base-types | |
/// Tested with Clang 3.6 rc 2 here: http://gcc.godbolt.org/ | |
/// MSVC++ 2013, Update 4. | |
/// ----- | |
template <typename T> | |
struct A { | |
typedef A<T> base_type; | |
typedef T value_type; | |
}; | |
template <typename T> | |
struct B : public A < T > { | |
// Uncomment ONE example below, and the corresponding callin main(). | |
// doesn't work in clang/gcc because base_type isn't inherited/visible: | |
// clang: "error: use of undeclared identifier 'base_type' | |
// vc++: "warning C4346: 'A<T>::value_type' : dependent name is not a type | |
// prefix with 'typename' to indicate a type" | |
// "error C2146: syntax error : missing ';' before identifier 'foo'" | |
//base_type::value_type foo() { return 0; } | |
// doesn't work in clang/gcc because base_type isn't inherited/visible | |
// clang: "error: use of undeclared identifier 'base_type' | |
// vc++: compiles without error | |
//typename base_type::value_type bar() { return 0; } | |
// clang/gcc: compiles without error. | |
// vc++: compiles without error | |
// ONE EXAMPLE, TWO LINES: | |
//typedef typename A<T>::base_type base_type; | |
//typename base_type::value_type bar2() { return 0; } | |
// Doesn't work in clang/gcc | |
// clang: "error: unknown type name 'value_type' | |
// vc++: compiles without error | |
value_type baz() { return 0; } | |
// clang/gcc: compiles without error. | |
// vc++: compiles without error | |
//typename A<T>::value_type baz2() { return 0; } | |
// Doesn't work in clang/gcc | |
// clang: "error: expected a qualified name after typename" | |
// vc++: compiles without error | |
//typename value_type blip() { return 0; } | |
}; | |
int main(int, char *[]) | |
{ | |
B<int> x; | |
//x.foo(); | |
//x.bar(); | |
//x.bar2(); | |
x.baz(); | |
//x.baz2(); | |
//x.blip(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
A couple of interesting posts on C++ 2-phase name lookup:
The accepted answer notes that MSVC doesn't perform two-phase lookup as per the standard:
http://stackoverflow.com/questions/12561544/two-phase-name-lookup-for-c-templates-why
http://blog.llvm.org/2009/12/dreaded-two-phase-name-lookup.html