Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RossBencina/157eecf2189739cd913f to your computer and use it in GitHub Desktop.
Save RossBencina/157eecf2189739cd913f to your computer and use it in GitHub Desktop.
Experiment: Inheriting Types From Template Base Class
/// 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();
}
@RossBencina
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment