The code below is adapted from the answer here: https://stackoverflow.com/a/17579889/352552
My purpose in asking this question is try to to understand better how C++ handles type resolution around dependent types, versus what's considered to be on the current instantiation, and therefore not needing a typename
qualifier. I've been getting contradictory results from different compilers, so I've come here looking for a more canonical answer.
Consider this code
#include <iostream>
struct B {
typedef int result_type;
};
template<typename T>
struct C {
};
template<>
struct C<float> {
typedef float result_type;
};
template<typename T>
struct D : B, C<T> {
std::string show() {
//A) Default to current instantiation - ignore dependent type, even if one exists, or so I hope
D::result_type r1;
//B) What **exactly** does typename add, here?
//typename D::result_type r1;
return whichType(r1);
}
std::string whichType (int val){
return "INT";
}
std::string whichType (float val){
return "FLOAT";
}
};
int main() {
D<std::string> stringD;
D<float> floatD;
std::cout<<"String initialization "<<stringD.show()<<std::endl;
std::cout<<"Float initialization "<<floatD.show()<<std::endl;
}
line A) in show()
, if I understand correctly, tells the compiler to use the current instantiation, so I should get INT INT. On GCC, I do. Cool.
Line B, again if understand correctly, should either tell the compiler to consider dependent types, which would make that line error out because of the ambiguity; or, if that means only consider dependent types, I should get INT FLOAT. On GCC I get INT INT there, too. Why?
Running this on Clang.
Line A doesn't compile at all.
error: no type named 'result_type' in 'D'; did you mean simply 'result_type'? D::result_type r1;
dropping the D::
does indeed yield INT INT.
Should it have compiled, or is Clang incorrect here?
Line B does indeed error on the ambiguity
error: member 'result_type' found in multiple base classes of different types typename D::result_type r1
Can anyone here say with authority which compiler (if any!) is canonically correct, and why?
Assuming Clang is correct, it would imply that
MyType::F
is invalid for referencing a type from the current instantiation if it exists on a base type; it's only valid if the type is defined on that class. Ie adding
typedef double dd;
to D
and then
D::dd d = 1.1;
std::cout<<d;
in show would work just fine, which is indeed the case.
Moreover,
typename D::sometype
means to consider dependent types, but not exclusively, and so expect errors if such a type winds up defined in multiple places, either in the current instantiation, and or dependent on a template parameter.
Link to GCC repl I was using: https://wandbox.org/
Link to Clang repl I was using: https://repl.it/languages/cpp11
Aucun commentaire:
Enregistrer un commentaire