2014-11-19 18 views
5

Zmierzyłem się z czymś, czego nie rozumiem, ani nie znalazłem sposobu, aby właściwie pracować. To, co próbuję osiągnąć, wygląda stosunkowo prosto: chcę porównać niektóre dane.Ekstrakcje szablonów Variadic

Najlepszy sposób, aby opisać byłaby linia kodu:

std::tuple<const char *, int, const char *, int> my_data = 
    std::make_tuple("hello", 13, "world", 37); 
// Now I want to compare my_data againt some known value. 
assert(Test::entry(my_data, "hello", 13, "world", 37)); 

używam krotki dla dobra przykładu. W moim przypadku dane te pochodzą z obiektu wiadomości i są wyodrębniane za pomocą operator>>. Jednak nie jest to związane z problemem.

Oto minimalistyczny kod ilustrujący problem.

#include <cstring> 
using MyTuple = std::tuple<const char *, int, const char *, int>; 

namespace Test 
{ 

    // called when we are done                                         
    bool extract(MyTuple source) 
    { 
    return true; 
    } 

    template<typename T, 
      typename ...Content> 
    bool extract(MyTuple source, T data, Content... content) 
    { 
    if (std::is_same<const char *, T>::value) 
     assert(0); // why ? :(                                         
    std::cout << "Generic: " << data << std::endl; 
    return extract(source, content...); 
    } 

    template<typename ...Content> 
    bool extract(MyTuple source, const char *str, Content... content) 
    { 
    std::cout << "Overloaded: " << str << std::endl; 
    return extract(source, content...); 
    } 

    template<typename ...Content> 
    bool entry(const std::tuple<const char *, int, const char *, int> &data, 
      Content... content) 
    { 
    return extract(data, content...); 
    } 

}; 

bym normalnie wykonywać comparaison w funkcjach extract(), ale dla zachowania przykład prostego, usunąłem je.

Co chcę osiągnąć, to właściwa wysyłka. Opierając się na przykładzie jest to moje zrozumienie, że nazywają zamówienie powinno być:

  1. Przeciążone dla const char *
  2. Generic
  3. przeciążeniem const char *
  4. Generic

Jednakże wyjściu tego testu Program jest następujący:

  1. Przeciążony: hello
  2. Ogólny: 13
  3. Assertion failed. Test std::is_same wyzwala assert.

Co odkryłem, że przeciążenie const char * nie zostanie wywołane po jednorazowym wywołaniu generycznego przeciążenia.

Brakuje mi czegoś?

EDYCJA: Nie, jeśli zdefiniuję przeciążenie const char * przed funkcją ogólną, to nawet nie skompiluje.

+0

To trochę głupie, aby użyć 'std :: make_tuple', kiedy już znasz typ krotki, którą chcesz - cały punkt' make_tuple' ma wydedukować typ krotki z typów inicjalizatorów. Równie dobrze możesz po prostu użyć 'std :: tuple my_data {" hello ", 13," world ", 37};' – Casey

+0

@Casey Yeah to było tylko dla zilustrowania mojego problem. Moje źródło danych to gniazdo, z którego wydobywam dane. – Xaqq

Odpowiedz

3

Należy również pamiętać, że jeśli zdefiniuję przeciążenie const char * przed funkcją ogólną, to nie skompiluje się.

Oświadczenie powinno wystarczyć:

template <typename... Content> 
bool extract(MyTuple source, const char *str, Content... content); // <- here 

template <typename T, typename... Content> 
bool extract(MyTuple source, T data, Content... content) 
{ 
    std::cout << "Generic: " << data << std::endl; 
    return extract(source, content...); 
} 

template <typename... Content> 
bool extract(MyTuple source, const char *str, Content... content) 
{ 
    std::cout << "Overloaded: " << str << std::endl; 
    return extract(source, content...); 
} 

Dlaczego?

Przeciążenie biorąc const char* nie jest widoczna podczas tego konkretnego wyszukiwania nazw bez wcześniejszej deklaracji. Niektóre wyjątki od tego można znaleźć w comments below.

+0

Wielkie dzięki. Teraz wszystko nabiera sensu. To również prawdopodobnie tłumaczy, dlaczego próba ukrycia funkcji za pomocą 'std :: enable_if' spowodowała błąd czasu kompilacji, ponieważ drugi nie był dostępny. – Xaqq

+0

Przyczyną, że nie można znaleźć przeciążenia "const char *", jest to, że nie znaleziono go przez niewykwalifikowane wyszukiwanie (w kontekście definicji) ani przez ADL. Jeśli 'MyTuple' nazwałby typ w przestrzeni nazw' Test', ADL używający kontekstu instancji pozwoliłby znaleźć przeciążenie 'const char *' nawet bez wcześniejszej deklaracji. –

+0

@ T.C. Nie sądzę, że rozumiem. Czy chodzi ci o 'typedef'ing' MyTuple' w przestrzeni nazw 'Test'? Czy mógłbyś podać przykład? – Xaqq

Powiązane problemy