2010-01-26 24 views
5

Yukarıdaki kurucu ile Foo türünde bir nesneyi nasıl başlatılamıyorum?C++ şablonlu kurucu, derleme yapamaz

I ("şablon typedefs" için geçici bir çözüm olarak) bir iç typedef kullanan bir sınıf Bar var ve aşağıda yapıcı (DURUM 1) kullanmak niyetinde. Ancak, derlemek için görünmüyor. Bu yasal C++ mı? ÖRNEK 2, sorunun Bar'daki typedef ile ilgili olduğunu öne sürmektedir.

Ben Bar'da türü ile nesnelerin std :: vektörleri kabul edecek bir kurucusu tanımlamak nasıl?

#include <vector> 
#include <iostream> 
#include <utility> 

template <typename T> 
struct Bar 
{ 
    typedef std::pair<T, T> type; // or anything else that uses T 
}; 

struct Foo 
{ 
    Foo() {} 

    // CASE 1: doesn't compile 
    template <typename T> explicit Foo(const std::vector<typename Bar<T>::type>& data) 
    { 
     std::cout << "Hello\n"; 
    } 

    //// CASE 2: compiles, but it's not what I want 
    //template <typename T> explicit Foo(const std::vector<Bar<T> >& data) 
    //{ 
    // std::cout << "Hello\n"; 
    //} 
}; 

int main() 
{ 
    std::vector<Bar<int>::type> v; // for CASE 1 
    //std::vector<Bar<int> > v; // for CASE 2 

    Foo f(v); 
    return 0; 
} 
+0

Hata çıktısını gönderir misiniz? 'Foo :: Foo (const Foo &)' : –

+0

VC++ kopya kurucu ile benim yapıcı karıştırır ve yazar 'const Foo &' GCC çıkışları için 'std :: vector <_Ty>' dan parametresini 1 dönüştürmek olamaz: 'Foo :: Foo (std :: vektör > &)' – kmhofmann

+1

çağrılması için eşleşen işlev yok. Intel C++ Derleyicisi, yapıcı bildirimi ile ilgili olarak aşağıdaki yardımcı yardımı verir: uyarı # 488 : "" T "şablon parametresi, işlev şablonunun parametre türlerini bildirmede kullanılmaz" Foo :: Foo (const std :: vektör :: type, std :: allocator :: type >> &) ' " –

cevap

9

bir şablon parametresi olmayan bir çıkarılmış bağlamda tek kullanılır C++ standart paragraf 14.8.2.1 göre, karşılık gelen şablon bağımsız değişken anlaşılamayanlar:

Bir şablon parametre bir işlev şablonunun işlevi parametrelerinin herhangi kullanılmaz veya olmayan çıkarılabilir bağlamda sadece kullanılır, buna karşılık gelen şablon argüman bir işlev çağrısı çıkarılabilir edilemez ve şablon argümanı açıkça belirtilmelidir .

§14.8.2.4 belirtildiği gibi nondeduced bağlamlarda tanımı:

nondeduced bağlamlarda şunlardır: bir tür

  • iç içe isim belirteci bu nitelikli kimlik numarası kullanılarak belirtildi.

  • Hangisi veya şablon bağımsız değişkenler daha fazlasında bir şablon kimliği olan A tipi

  • bir şablon parametre başvuran bir ifadesidir.

Bar<T>::type yılında Bar<T> bir iç içe-ad-belirteci ve dolayısıyla olmayan bir çıkarılabilir bağlam, yani açıkça (yapıcı ... mümkün değildir çağıran şablon argümanı belirtmelisiniz yani Foo f<int>(v) yazamazsınız.

Ben en azından hantal ve daha muhtemelen imkansız olurdu, çünkü derleyici şablon argümanı anlamak olamaz herhalde: std::vector<std::pair<int,int> > ile Foo yapıcısını çağrılırken

template<typename T> 
struct Bar 
{ 
    typedef std::pair<T,T> type; 
}; 

template<> 
struct Bar<char> 
{ 
    typedef std::pair<int,int> type; 
}; 

Şimdi bir belirsizlik vardır: Bar uzman olduğunu hayal edin: şablon argümanı int veya char olmalıdır? Ve böyle bir belirsizlik olmasa bile, derleyicinin doğru typedef ile örneklemeyi bulmadan önce potansiyel olarak herhangi bir türle Bar'ı başlatması gerekeceğini kolayca görebilirsiniz (iyi, yukarıdaki ifadelerin gerçekten sık sık olduğundan emin değilim) Ben düşündüğümden çok daha zeki olmak için derleyicileri bul!)

+0

Ayrıca iki nondeduced bağlamları isimleri 14.8.2.4/4, alıntı yapabilirsiniz. –

+0

İşaretçi için teşekkürler, bilgileri ekledim. –

4

Sizin yapıcı geçerli:

template <typename T> 
explicit 
Foo(const std::vector<typename Bar<T>::type>& data) 

argüman T fonksiyon argüman bu şekilde çıkarılabilir edilemez şablonu. (Ben bu bir "non-deducible bağlam" denir düşünüyorum, ama emin değilim.) Bu sadece işe yaramaz

. Bunun yerine

template <typename B> 
explicit 
Foo(const std::vector<B>& data) 

yazıp B tip typename Bar<T>::type ait olduğunu iddia için başka yollar bulmak gerekecek.

+0

Ah, Luc oldukça belirsiz stama bölüm ve ayette sağladı." tement: http://stackoverflow.com/questions/2140025/c-templated-constructor-wont-compile/2140182#2140182 – sbi

0

Bunun için tek neden, "merhaba" basmak yerine karşılık gelen türdeki bir Çubuğu başlatmak istediğinizdir.

Belki ters yönde (eğer derleyici gerçekleştirmek mümkün olacaktır umuyor ters kesinti tür) 'de türlerini haritalama deneyebilirsiniz:

#include <utility> 
#include <vector> 

template <class T> 
struct BarType; 

template <class T> 
struct BarType<std::pair<T, T> > 
{ 
    typedef T type; 
}; 

template <class T> 
struct Bar {}; 

struct Foo 
{ 
    template <class T> 
    Foo(const std::vector<T>&) 
    { 
     Bar<typename BarType<T>::type> bar; 
     //... 
    } 
}; 

int main() 
{ 
    Foo(std::vector<std::pair<int, int> >()); 
} 
0

Acaba sizin için bu işi gibi bir şey mi?

#include <vector> 
#include <iostream> 
#include <utility> 
#include <boost/static_assert.hpp> 

template <typename T> 
struct Bar 
{ 
    typedef std::pair<T, T> type; // or anything else that uses T 
    enum {val = 42}; 
}; 

template <typename T> 
struct Traits 
{ 
    enum {allowed = false}; 
}; 

template <typename T> 
struct Traits<std::pair<T, T> > 
{ 
    enum {allowed = true}; 
    typedef Bar<T> BarType; 
}; 

struct Foo 
{ 
    Foo() {} 

    template <typename T> explicit Foo(const std::vector<T>& data) 
    { 
     BOOST_STATIC_ASSERT(Traits<T>::allowed); 
     typedef typename Traits<T>::BarType BarType; 
     std::cout << BarType::val << std::endl; 
    } 
}; 

int main() 
{ 
    std::vector<Bar<int>::type> v; 
    std::vector<float> v2; 

    Foo f(v); 
// Foo f2(v2); // Compile error 
    return 0; 
} 

Bu, derleme ve GCC 4.4.1 üzerinde çalışır. Traits, kurucunuz tarafından izin verilen diğer vector::value_type için uzmanlaşabilirsiniz.