Następujący fragment kodu kompiluje się w języku i MSVS, ale nie w gcc.Błąd w gcc lub rozszerzenie w klang/MSVS
template<typename T> class clone_ptr;
template<typename T, typename U, typename ...Args>
clone_ptr<T> make_cloned(Args ...args);
// note: everything not needed for example cut out, so
// this class is neither complete nor correct
template<typename T>
class clone_ptr
{
public:
clone_ptr() : ptr(nullptr) {}
operator bool() { return ptr!=nullptr; }
T* operator->() { return ptr; }
private:
clone_ptr(T* p) : ptr(p) {}
T* ptr;
template<class T1,class U1, typename ...Args>
friend clone_ptr<T1> make_cloned(Args ...args);
};
template<typename T, typename U=T, typename ...Args>
clone_ptr<T> make_cloned(Args ...args)
{
return {new U(args...)};
}
// ----------------------------------------------
#include <string>
#include <vector>
#include <iostream>
using namespace std;
struct Base
{
int a;
Base(int a=0) : a(a) {}
virtual string foo() { return "Base "+to_string(a); };
virtual ~Base() {}
};
struct Sub : Base
{
Sub(int a=0) : Base(a) {}
virtual string foo() override { return "Sub "+to_string(a); };
};
string testit()
{
std::vector< clone_ptr<Base> > vec;
vec.push_back(make_cloned<Base>(7));
vec.emplace_back();
vec.push_back(make_cloned<Base,Sub>(5));
string ss;
for(auto&& a : vec)
{
ss += a?a->foo():"<empty>";
}
return ss;
}
int main()
{
cout << testit() << endl;
}
gcc narzeka:
error: no matching function for call to 'make_cloned(int)'
vec.push_back(make_cloned<Base>(7));
note: candidate is:
note: template<class T, class U, class ... Args> clone_ptr<T> make_cloned(Args ...)
clone_ptr<T> make_cloned(Args ...args)
^
note: template argument deduction/substitution failed:
note: couldn't deduce template parameter 'U'
vec.push_back(make_cloned<Base>(7));
Jest to błąd w gcc, i czy istnieje obejście że tylko opiera się na standardowej zgodnej C++?
Jakiej wersji GCC używasz? Czy próbowałeś już tego, 4.9.2? – usr1234567
g ++ --version daje 'g ++ (GCC) 4.9.2' – sp2danny
Rzeczywiście, wystąpił błąd w GCC 4.9.2 i jest skompilowany z Clang 3.5 –