3

Рассмотрим следующий код:Временное решение для GCC 4.8.1: извините, невыполненными: коверкая argument_pack_select

#include <tuple> 

template <class Result, class Function, class... Types> 
Result f(Function func, Types... values) 
{ 
    return std::get<0>(std::make_tuple(func(values)...)); 
} 

template <class... Types> 
int g(const Types... values) 
{ 
    return std::get<0>(std::make_tuple(f<Types>([](int n){return n;}, values)...)); 
} 

int main() 
{ 
    return g(42); 
} 

Под г ++ 4.8.1, он производит:

mangling.cpp: In instantiation of ‘g(const Types ...) [with Types = int]::__lambda0’: 
mangling.cpp:12:50: required from ‘struct g(const Types ...) [with Types = int]::__lambda0’ 
mangling.cpp:12:77: required from ‘int g(const Types ...) [with Types = int]’ 
mangling.cpp:17:16: required from here 
mangling.cpp:12:57: sorry, unimplemented: mangling argument_pack_select 
    return std::get<0>(std::make_tuple(f<Types>([](int n){return n;}, values)...)); 
                 ^
mangling.cpp: In instantiation of ‘struct g(const Types ...) [with Types = int]::__lambda0’: 
mangling.cpp:12:77: required from ‘int g(const Types ...) [with Types = int]’ 
mangling.cpp:17:16: required from here 
mangling.cpp:12:57: sorry, unimplemented: mangling argument_pack_select 
mangling.cpp:12:57: sorry, unimplemented: mangling argument_pack_select 
mangling.cpp:4:8: error: ‘Result f(Function, Types ...) [with Result = int; Function = g(const Types ...) [with Types = {int}]::__lambda0; Types = {int}]’, declared using local type ‘g(const Types ...) [with Types = {int}]::__lambda0’, is used but never defined [-fpermissive] 
Result f(Function func, Types... values) 

Есть обходной путь, чтобы избежать Эта проблема ? Сообщено ли о нем и исправлено в g ++ 4.8.2 или 4.9.0?

EDIT: Я только что сообщил об ошибке здесь: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60130

+0

Дает ICE в GCC 4.9. –

+0

Vincent: Отправьте пример реальной проблемы, которую вы пытаетесь решить. @ Ответ Дэниэлла верно: если вы просто пытаетесь избежать ICE, все, что вам нужно сделать, это вытянуть лямбду за пределы расширения пакета. (Если вам это нужно 'constexpr', решение будет таким же. Я могу опубликовать код, но я бы предпочел не отвлекаться от ответа Даниэля, прежде чем вы сказали нам все ваши секретные требования.) – Quuxplusone

+0

@Quuxplusone Я имею дело с код, основанный на самых ужасных/элегантных трюках метапрограммирования, и я выделил проблему в этом примере. Но в принципе, мне нужно сделать то же самое, что вызывает проблемы в приведенном примере (это не проблема XY). – Vincent

ответ

3

вам нужна новая лямбда для каждого из расширенных параметров? В противном случае это фиксирует это:

template <class... Types> 
int g(const Types... values) 
{ 
    auto func = [](int n){return n;}; 
    return std::get<0>(std::make_tuple(f<Types>(func, values)...)); 
} 

Live example

+0

В моем производственном коде, Мне нужно, чтобы функция была constexpr ... – Vincent

+0

@Vincent Не уверен, что C++ 1y является для вас вариантом, и если он действительно работает с 'constexpr', но [возможно, это] (http: //coliru.stacked-crooked .com/a/da04662afe354ab0) помогает? –

+0

@ Daniel В C++ 1y вы можете просто добавить 'constexpr' в функцию, которую вы написали в своем ответе! Во всяком случае, в C++ 11 вы можете constexprствовать все с подходящим использованием вспомогательных функций. I.e., вы бы выполнили 'g' как' return ghelper ([] (int n) {return n;}, values ​​...); 'где' ghelper' реализуется очевидным образом. – Quuxplusone