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
struct B {
typedef int result_type;
};
template
struct C {
};
template<>
struct C {
typedef float result_type;
};
template
struct D : B, C {
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 stringD;
D floatD;
std::cout<<"String initialization "< std::cout<<"Float initialization "< }
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. So far, so good.
Line B, again if I 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 correct 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 might 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<
in show
would work just fine, which is indeed the case.
Moreover,
typename D::sometype
seems to mean 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.
But again, this all assumes Clang's behavior is correct according to spec, which I can't speak to.
Link to GCC repl I was using:
https://wandbox.org/
Link to Clang repl I was using:
https://repl.it/languages/cpp11
No comments:
Post a Comment