Невозможно создать экземпляры шаблонов функций, которые используют Decltype для вывода возврата типа, если это вызвано изнутри лямбды?

StackOverflow https://stackoverflow.com/questions/2335530

Вопрос

Я пытаюсь использовать C ++ 0x, и, в частности, Lambda Expression и Decltype, чтобы упростить часть моего кода, используя компилятор RC MSVC10.

Я столкнулся со следующей очень странной проблемой:

template <typename F>
auto foo(F f) -> decltype(f()){
  return f();
}

template <typename F>
void bar(F f){
  f();
}

int main() {
  bar([](){
    foo([]() { }); // error C2893: Failed to specialize function template ''unknown-type' foo(F)'
  });
}

Как указано в комментарии, компилятор генерирует ошибку в строке foo([]() { }).

Я ненавижу кричать «ошибка компилятора», но я действительно не вижу хорошего объяснения этой ошибки. Видимо, в то время как внутри внешнего выражения лямбда компилятор не может специализировать foo Функциональный шаблон для внутренней Lambda.

Однако, если определение foo изменяется на хард -код типа возврата, например:

template <typename F>
void foo(F f){
  return f();
}

Тогда все хорошо компилируется.

Есть ли какая -то неясная причуда Descltype, когда используется для вывода возврата типа параметров выражения лямбды внутри прицела другой лямбды, о которой я не знаю?

Это было полезно?

Решение

Это лишь некоторые тестовые случаи для людей, которые можно наблюдать.

Работает

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

void dummy() {}

int main()
{
    auto x = []()
            {   // non-lambda parameter
                foo(dummy);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto f = [](){};
    auto x = [&]()
            {    // pre-defined lambda
                foo(f);
            };
}

Терпит неудачу

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda
                foo([]{});
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda
                auto f = []{};
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-scope lambda, explicit return
                // (explicit return type fails too, `-> void`)
                auto f = [](){ return; };
                foo(f);
            };
}

template <typename F>
auto foo(F f) -> decltype(f())
{
  return f();
}

int main()
{
    auto x = []()
            {   // in-argument lambda, explicit return non-void
                // (explicit return type fails too, `-> int`)
                foo([]{ return 5; }); 
            };
}

Так что, похоже, связано с масштабами и void Тип внутренней лямбды, даже когда он был явным.(?)

Другие советы

Характер «Авто» позволяет компилятору рассчитать тип. Но ваш первый пример содержит рекурсивные ссылки друг на друга, поэтому для расчета автомобилей Foo вам нужен планка и создать экземпляр панели, который вам нужен Foo.

С другой стороны, второй пример явно говорит компилятору: «Это должен быть указатель для функционирования, так что успокаивайте на некоторое время». Поскольку указатель на функцию хорошо рассчитывается компилятор типа знает, что именно будет зарезервировано. Просто для аналога: сравните заявление участника

struct A; //forward
...
A a1; //this is an error
A *a2; //this is correct since pointer calculated in bytes
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top