Следующий код компилируется просто отлично: (без пространства имен)
#include <vector>
template <class T>
void foo(const int & from, std::vector<T> & to)
{
for (int i = 0; i < 5; i++)
{
T bar;
foo(from, bar);
to.push_back(bar);
}
}
struct Bar
{
int a;
int b;
};
struct Baz
{
std::vector<Bar> bars;
};
void foo(const int & from, Bar & to)
{
to.a = from;
to.b = from - 1;
}
void foo(const int & from, Baz & to)
{
foo(from, to.bars);
}
void fooTest()
{
int num = 10;
Baz baz;
foo(num, baz);
}
int main()
{
fooTest();
}
Но когда я представляю пространство имен для Bar и Baz, он не компилируется. (с пространством имен)
#include <vector>
template <class T>
void foo(const int & from, std::vector<T> & to)
{
for (int i = 0; i < 5; i++)
{
T bar;
foo(from, bar);
to.push_back(bar);
}
}
// When I add this namespace, it fails to compile
namespace BarBar
{
struct Bar
{
int a;
int b;
};
struct Baz
{
std::vector<Bar> bars;
};
}
void foo(const int & from, BarBar::Bar & to)
{
to.a = from;
to.b = from - 1;
}
void foo(const int & from, BarBar::Baz & to)
{
foo(from, to.bars);
}
void fooTest()
{
int num = 10;
BarBar::Baz baz;
foo(num, baz);
}
int main()
{
fooTest();
}
Отображается ошибка:
with_namespace.cpp: In instantiation of ‘void foo(const int&, std::vector<T>&) [with T = BarBar::Bar]’:
with_namespace.cpp:37:22: required from here
with_namespace.cpp:9:12: error: no matching function for call to ‘foo(const int&, BarBar::Bar&)’
foo(from, bar);
^
with_namespace.cpp:4:6: note: candidate: template<class T> void foo(const int&, std::vector<T>&)
void foo(const int & from, std::vector<T> & to)
^
with_namespace.cpp:4:6: note: template argument deduction/substitution failed:
with_namespace.cpp:9:12: note: ‘BarBar::Bar’ is not derived from ‘std::vector<T>’
foo(from, bar);
^
Также обратите внимание, что код с пространством имен компилируется очень хорошо при использовании MSVC.Почему компилятор не может найти определение при использовании пространства имен?
Я использую следующую версию: g ++ (Ubuntu 5.4.0-6ubuntu1 ~ 16.04.9) 5.4.0 20160609
ОБНОВЛЕНИЕ: После того, как @MM указал на то, как функция поиска работает для шаблонов и ADL, я пошел со следующим исправлением:
#include <vector>
template <class T>
void foo(const int & from, std::vector<T> & to)
{
for (int i = 0; i < 5; i++)
{
T bar;
foo(from, bar);
to.push_back(bar);
}
}
namespace BarBar
{
struct Bar
{
int a;
int b;
};
struct Baz
{
std::vector<Bar> bars;
};
};
// Put them in the same namespace as Bar so that the templated foo find this function
namespace BarBar
{
using ::foo; // We are going to use templated foo in the latter functions
void foo(const int & from, BarBar::Bar & to)
{
to.a = from;
to.b = from - 1;
}
void foo(const int & from, BarBar::Baz & to)
{
foo(from, to.bars);
}
}
void fooTest()
{
int num = 10;
BarBar::Baz baz;
BarBar::foo(num, baz);
}
int main()
{
fooTest();
}