Re: class inside of template puzzler
Jason Turner wrote:
#include <map>
template<class P1>
struct T
{
struct T2
{
T2() {}
};
T()
{
std::map<std::string, T2> m;
Case 1: Although T2 is a dependent type, std::map<std::string,T2> can only
ever be interpretted here as a type. There is no need for typename because
we are not using any member (function, typedef or variable) of
std::map<std::string,T2> but rather just that type itself to define "m".
std::map<std::string, T2>::iterator itr1 = m.begin();
Case 2: T2 is a dependent name since T2 is a nested class within the T class
template. This makes std::map<std::string,T2> also dependent, so you need a
typename out the front to designate that "iterator" is a type within the
std::map template, not a member variable:
typename std::map<std::string, T2>::iterator itr1 = m.begin();
std::map<std::string, T::T2>::iterator itr2 = m.begin();
Case 3: Like the previous case, only here you also need a typename in front
of T::T2. I guess this is because T on its own still does not name a
specific instantiation of the template (you would need to have an argument
to do that, such as T<int>). I'm a little surprised that T::T2 is not
equivalent to simply T2 in this context, but I am a little pressed for time
right now and will leave it to others to explain why this is the case. This
line should be:
typename std::map<std::string, typename T::T2>::iterator itr2 = m.begin();
std::map<std::string, T<P1>::T2 >::iterator itr3 = m.begin();
Case 4: Again, same discussion as previous case. Adding an explicit argument
of P1 doesn't change things, since T<P1> is still not a specific
instantiation:
typename std::map<std::string, typename T<P1>::T2 >::iterator itr3 =
m.begin();
std::map<std::string, T<int>::T2 >::iterator itr4 = m.begin();
// Compiles, but not really useful
Case 5: On the contrary, this could still be useful. Here, T<int> defines a
specific instantiation and the definition of T<int> is fully known.
Therefore, the compiler has all the information it needs to determine that
T2 is indeed unambiguously a type and this is why you don't need the
typename keyword in this particular case.
typename std::map<std::string, T2>::iterator itr5 = m.begin();
// Works as expected
Case 6: Correct, as per case 2 discussion.
}
};
int main() {}
--
Craig Scott
Computational Modeling, CSIRO (CMIS)
Melbourne, Australia
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]