2014-11-19 3 views
5

Я столкнулся с чем-то, чего я не могу понять и не нашел способ нормально работать. То, что я пытаюсь достичь, выглядит относительно просто: я хочу сравнить некоторые данные.Выбросы шаблонов Variadic

Лучший способ описать бы строка кода:

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

Я использую кортеж ради примера. В моем случае эти данные поступают из объекта сообщения и извлекаются с использованием operator>>. Однако это не связано с проблемой.

Вот минималистский код, иллюстрирующий проблему.

#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...); 
    } 

}; 

Я бы нормально выполнять comparaison в extract() функций, но и для поддержания пример простой, я удалил их.

То, что я хочу достичь, является правильной отправкой. На примере это мое понимание того, что называют порядок должен быть:

  1. перегружен const char *
  2. Generic
  3. перегрузки для const char *
  4. Generic

Однако, выхода из этого теста Программа представляет собой:

  1. Перегружен: привет
  2. Генеральный директор: 13
  3. Assertion failed. Тест std::is_same запускает assert.

Я обнаружил, что перегрузка const char * не будет вызываться после того, как общая перегрузка была вызвана один раз.

У меня пропало что-то?

РЕДАКТИРОВАТЬ: Также не так, если я определяю перегрузку const char * перед общей функцией, это обыкновение даже компилировать.

+0

Немного глупо использовать 'std :: make_tuple', когда вы уже знаете тип кортежа, который вы хотите - вся точка' make_tuple' должна выводить тип кортежа из типов инициализаторов. Вы можете просто использовать 'std :: tuple my_data {" hello ", 13," world ", 37};' – Casey

+0

@Casey Да, это было только для иллюстрации моего проблема. Мой источник данных - это сокет, из которого я извлекаю материал. – Xaqq

ответ

3

Также отметим, что если я определяю const char * перегрузки перед родовой функции, это обыкновение даже скомпилировать.

Заявление должно хватить:

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

Почему?

Перегрузка с const char* не виден в течение этого конкретного имени поиска без предварительного объявления. Некоторые из этих исключений можно найти в comments below.

+0

Большое спасибо. Все это имеет смысл сейчас. Это также, вероятно, объясняет, почему попытка скрыть функцию с помощью 'std :: enable_if' вызвала ошибку времени компиляции, поскольку другая была недоступна. – Xaqq

+0

Причина, по которой перегрузка 'const char *' не может быть найдена, заключается в том, что она не найдена с помощью неквалифицированного поиска (с использованием контекста определения) и недоступна ADL. Если 'MyTuple' назвал тип в пространстве имен' Test', ADL, использующий контекст экземпляра, позволил бы найти перегрузку 'const char *' даже без предварительного объявления. –

+0

@ T.C. Я не думаю, что понимаю. Вы имеете в виду 'typedef'ing' MyTuple' внутри пространства имен 'Test'? Не могли бы вы привести пример, пожалуйста? – Xaqq

Смежные вопросы