Я немного играю со статическим полиморфизмом, я вызываю функцию, которая внутренне вызывает "правильную" специализированную функцию в зависимости от типа исходного аргумента (в основном я делаю тегирование). Вот код:
#include <iostream>
using namespace std;
// tags
struct tag1{};
struct tag2{};
// the compliant types, all should typedef tag_type
struct my_type1
{
using tag_type = tag1;
};
struct my_type2
{
using tag_type = tag2;
};
// static dispatch via tagging
template <typename T>
void f(T)
{
cout << "In void f<typename T>(T)" << endl;
// why can I call f_helper without forward definition?!?
f_helper(typename T::tag_type{});
}
int main()
{
my_type1 type1;
my_type2 type2;
// how does f below knows about f_helper ?!?!
// even after instantiation f_helper shouldn't be visible!
f(type1);
f(type2);
}
// helper functions
void f_helper(tag1)
{
cout << "f called with my_type1" << endl;
}
void f_helper(tag2)
{
cout << "f called with my_type2" << endl;
}
Итак, f(T)
вызывается с параметром my_type1
или my_type2
, который внутренне должен typedef tag_type
с соответствующим тегом tag1
/tag2
. В зависимости от этого внутреннего tag_type
, тогда вызывается "правая" оболочка, и это решение делается, конечно, во время компиляции. Теперь я действительно не понимаю, почему этот код работает? Почему нам не нужно пересылать-объявлять f_helper
? У меня сначала были обертки, определенные до main
(и после f
), и я, хотя это нормально, имеет смысл, вам не нужно пересылать объявление, потому что компилятор создает экземпляр шаблона только при вызове f(type1);
(в main()
), прежде чем он не знает тип T
, поэтому во время создания экземпляра компилятор знает f_wrapper
.
Но, как вы видите, даже если я объявляю обертку ПОСЛЕ main()
, код все еще работает. Почему это происходит? Я думаю, вопрос немного странный, спрашивая, почему работает код:)
ИЗМЕНИТЬ
Код продолжает компилироваться даже в gcc5 и gcc HEAD 6.0.0.