2015-03-18 4 views
0

Я пытаюсь создать переменную функцию шаблона, которая считывает элементы по порядку (с индексом). Цель состоит в том, чтобы вызвать функцию read_tuple для чтения двух int с идентификаторами 0 и 1 (с read_int (0) и read_int (1)).Вариант расширения шаблона шаблона Variadic id

Вот код, я до сих пор:

int data[] = {10,20,30,40}; 

int int_read(int id) 
{ 
    return data[id]; 
} 

template <typename T> 
T read(int& index) 
{ 
    index--; 
    int value = int_read(index); 
    std::cout << "index :" << index << " value: " << value << std::endl; 
    return value; 
} 

template <typename... Args> 
std::tuple<Args...> read_tuple() 
{ 
    int index = sizeof...(Args); 
    return std::tuple<Args...>(read<Args>(index)...); 
} 

Я могу назвать это так:

auto tuple = read_tuple<int, int>(); 
std::cout << "First: " << std::get<0>(tuple) << std::endl; 

И я получаю следующий результат:

index :1 value: 20 
index :0 value: 10 
First: 10 

Однако, этот код зависит от порядка оценки функции чтения. Как я могу генерировать индекс, зависящий от расширения пакета (чтобы избежать неопределенного поведения)?

+1

с помощью рамно-Init-список 'станд :: кортеж {читать (индекс) ...}' вы гарантированно исполнение в порядке их появления (т.е. слева направо) –

ответ

3

Как указал Петр, порядок оценки гарантирован, если вы используете бит-init-list. Будьте осторожны, хотя если вы используете GCC до 4.9.1, так как он не работает (c.f. Evaluation order (sequenced-before relation) among initializer-clauses in braced-init-list).

Если вы используете версию, которая не гарантирует порядок инициализации (или просто хочет, чтобы генерировать идентификаторы), вы можете использовать индексатор (от other stackoverflow post):

template<int... I> struct index { 
    template<int n> using append = index<I..., n>; 
}; 
template<int N> struct make_index { 
    typedef typename make_index<N - 1>::type::template append<N - 1> type; 
}; 
template<> struct make_index<0> { typedef index<> type; }; 
template<int N> using indexer = typename make_index<N>::type; 

Вы можете использовать его так:

int data[] = {10,20,30,40}; 

int int_read(int id) 
{ 
    return data[id]; 
} 

template <typename T> 
T read(int index) 
{ 
    int value = int_read(index); 
    std::cout << "index :" << index << " value: " << value << std::endl; 
    return value; 
} 

template <typename... Args, int... i> 
std::tuple<Args...> read_tuple_indexed(index<i...>) 
{ 
    return std::tuple<Args...>(read<Args>(i)...); 
} 

template <typename... Args> 
std::tuple<Args...> read_tuple() 
{ 
    return read_tuple_indexed<Args...>(indexer<(sizeof...(Args))>()); 
} 
Смежные вопросы