G++, clang++ and std::function

10

我只是在尝试使用C++11中的新std::function,并编写了一个例子,它可以与clang++ 3.2和Intel C++编译器13.1一起编译,但无法与g++ 4.8一起编译。在我报告此问题之前,我想检查一下自己是否做了什么非常愚蠢的事情,以及这个代码片段是否应该编译通过。 那么,以下代码是否有效的C++11代码?

template <typename C>
void map(C& c, std::function<typename C::value_type(typename C::value_type)> f)
{
    for(auto& x : c) {
        x = f(x);
    }
}

int main()
{
    std::vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    map(v, [](int x) { return x+2; });

    for(auto x : v) {
        std::cout << x << std::endl;
    }
}

我意识到这段代码并不是很有用,但令我感到奇怪的是,clang和Intel C++编译了它,而gcc没有。

编辑:当传递map一个函数对象或函数指针时,gcc也无法编译相同的代码:

struct {
    int operator() (int a) {
        return a+2;
    }
} add2s;
map(v, add2s);

int add2 (int a) {
    return a+2;
}
map(v,add2);

clang和icpc也都可以编译这两个。


你看到的 g++ 错误是什么? - Kiril Kirov
可能是重复问题:https://dev59.com/amkw5IYBdhLWcg3wSorA - filmor
@AndyProwl 好的。不过,这似乎在所有编译器中都可以工作 http://liveworkspace.org/code/6UvzJ$0 - balki
1
@AndyProwl,你是正确的,这里 不应该 有任何类型推导,因为 function<typename C::value_type(typename C::value_type)> 是一个非推导上下文,但出于某些原因它会失败,但使用 std::function<int(int)> 就可以正常工作,而这两者应该是等价的。更多详情请参见 bugzilla 报告。 - Jonathan Wakely
1
@JonathanWakely:再次感谢您的澄清。您的回答明确表明,更改本身只有帮助揭示了一个现有的错误,而不是导致问题的罪魁祸首。(已经+1赞) - Andy Prowl
显示剩余13条评论
1个回答

10

这是一个G++的bug,可以通过以下示例进行简化,该示例不使用std::function(或标准库中的任何内容):

template<typename T>
struct function
{
    function(int)
    { }
};

struct V {
  typedef int value_type;
};

template <typename C>
void map(C&, function<typename C::value_type>)
{
}

int main()
{
  V v;
  map(v, 1);
}

我已经将其报告给bugzilla,作为PR 56874。问题与lambda表达式无关,而是在非推导上下文中出现的一种类型错误地导致了参数推导失败。


也许您可以将有关非推断上下文的部分从您的评论添加到您的答案中。 - Stephan Dollberg
顺便提一下,您报告说这是针对lambda表达式的特定问题,但是当传递函数对象或函数指针时,它也无法编译。这是一个不同的错误还是相同错误的一部分? - dtruby
@dtruby,我已经更新了上面的答案和bugzilla报告:当传递一个“int”时,它也无法编译。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接