2015-03-04 9 views
6

Aşağıdaki kod parçacığı, clang ve MSVS'de derler, ancak gcc'de değil.Hata, gcc veya uzama clang/MSVS

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)); 

bu gcc bir hata mıdır ve sadece standart uyumlu C dayanan bir çözüm vardır ++:

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 şikayet?

+1

Hangi GCC sürümünü kullanıyorsunuz? Süreyi denedin mi, 4.9.2? – usr1234567

+0

g ++ --version g ++ (GCC) verir 4.9.2' – sp2danny

+0

Gerçekten de, GCC 4.9.2 ile bir hata oluştu ve Clang 3.5 –

cevap

2

Gerçekten de bu bir hata gibi görünüyor. Bir geçici çözüm, varsayılan şablon parametresini ikinci bir işleve ayırmaktır.

template<class T1, typename ...Args> 
    friend clone_ptr<T1> make_cloned(Args ...args); 
template<class T1, class U1, typename ...Args> 
    friend clone_ptr<T1> make_cloned(Args ...args); 

ve tanımı kolaydır: clone_ptr içinde, daha sonra iki arkadaş var

template<typename T, typename ...Args> 
clone_ptr<T> make_cloned(Args ...args) { return {new T(args...)}; } 
template<typename T, typename U, typename ...Args> 
clone_ptr<T> make_cloned(Args ...args) { return {new U(args...)}; } 

gcc 4.8.3, clang 3,5 ile test edilmiştir.

Düzenleme:

  1. tamamen

    // this is not needed: 
    template<typename T, typename U, typename ...Args> 
    clone_ptr<T> make_cloned(Args ...args); 
    
  2. Taşı şablon işlevi beyanı çıkarın: İki farklı şekillerde gcc 4.8.3 ile çalışan kodunuzu almak başardı araştırdıktan sonra şablon işlevi tanımından varsayılan şablon parametresi tanımı bildirime:

    template<typename T, typename U = T, typename ...Args> 
    clone_ptr<T> make_cloned(Args ...args); 
    
    template<typename T, typename U, typename ...Args> 
    clone_ptr<T> make_cloned(Args ...args) 
    { 
        return {new U(args...)}; 
    } 
    

Bunun hala gcc ile ilgili bir sorun olduğunu varsayardım, ancak bu şekilde kodunuz çalışır.