与GCC/MSVC中的lambda转换构造函数不一致

Discrepancy with lambda conversion constructor in GCC/MSVC

本文关键字:转换 构造函数 不一致 lambda 中的 GCC MSVC      更新时间:2023-10-16

哪一个(如果不是两者)正在破坏规范?在MSVC 2013和MSVC 2013年11月CTP上与MSVC一起尝试,GCC为MinGW x64 4.9.1,-std=c++11。

template<typename ret_type>
class memoizer
{
    using func_type = ret_type(*)(const int);
    const func_type func;
    std::map<int, ret_type> cache;
public:
    memoizer(func_type func) : func(func)
    {
    }
    ret_type operator [](const int n)
    {
        const auto it = cache.find(n);
        if(it != cache.end())
            return it->second;
        return cache[n] = func(n);
    }
};
//works in GCC but not MSVC
//error C2065: 'fib' : undeclared identifier
memoizer<int64_t> fib([](const int n)
{
    return n < 2 ? n : fib[n - 1] + fib[n - 2];
});
//works in MSVC but not GCC
//error: conversion from '<lambda(int)>' to non-scalar type 'memoizer<long long int>' requested
memoizer<int64_t> fib = [](const int n)
{
    return n < 2 ? n : fib[n - 1] + fib[n - 2];
};

这似乎源于他们以不同的方式处理lambda类型,以及当他们考虑定义变量时。

GCC是对的。

对于您的第一张表格:

变量被认为是在声明符的末尾声明的,声明符在初始化符之前。这就是为什么这个表格是有效的。著名的例子是int i = i;,它在语法上是有效的,并用自己的(不确定的)值初始化i

对于您的第二种形式:

使用=初始化失败,因为您有两个用户定义的转换。(lambda类型的转换运算符被认为是用户定义的。)它类似于

struct A { };
struct B { B(A) { } };
struct C { C(B) { } };
A a;
C c1(a); // okay
C c2 = a; // error