gpt4 book ai didi

c++ - 跨 C++0x 编译器的 lambda 特征不一致

转载 作者:IT老高 更新时间:2023-10-28 22:30:35 27 4
gpt4 key购买 nike

我观察到两个编译器(g++ 4.5、VS2010 RC)在将 lambdas 与类模板的部分特化匹配的方式上存在一些不一致。我试图为 lambdas 实现类似 boost::function_types 的东西来提取类型特征。查看 this了解更多详情。

在 g++ 4.5 中,lambda 的 operator() 的类型似乎类似于独立函数 (R (*)(...)) 的类型,而在 VS2010 RC 中,它看起来就像一个成员函数(R(C::*)(...))。所以问题是编译器编写者可以自由地解释他们想要的任何方式吗?如果不是,哪个编译器是正确的?请参阅下面的详细信息。

template <typename T>
struct function_traits
: function_traits<decltype(&T::operator())>
{
// This generic template is instantiated on both the compilers as expected.
};

template <typename R, typename C>
struct function_traits<R (C::*)() const> { // inherits from this one on VS2010 RC
typedef R result_type;
};

template <typename R>
struct function_traits<R (*)()> { // inherits from this one on g++ 4.5
typedef R result_type;
};

int main(void) {
auto lambda = []{};
function_traits<decltype(lambda)>::result_type *r; // void *
}

此程序在 g++ 4.5 和 VS2010 上都可以编译,但实例化的 function_traits 与代码中所述不同。

最佳答案

我认为 GCC 不合规。 N3092 §5.1.2/5 说

The closure type for a lambda-expression has a public inline function call operator (13.5.4) whose param- eters and return type are described by the lambda-expression’s parameter-declaration-clause and trailing- return-type respectively. This function call operator is declared const (9.3.1) if and only if the lambda- expression’s parameter-declaration-clause is not followed by mutable.

因此,虽然闭包对象类型的许多事情是实现定义的,但函数本身必须是 public 的成员,并且必须是非静态成员才能成为 const .

编辑:这个程序表明operator()是GCC 4.6上的一个成员函数,与4.5基本相同。

#include <iostream>
#include <typeinfo>
using namespace std;

template< class ... > struct print_types {};

template<> struct print_types<> {
friend ostream &operator<< ( ostream &lhs, print_types const &rhs ) {
return lhs;
}
};

template< class H, class ... T > struct print_types<H, T...> {
friend ostream &operator<< ( ostream &lhs, print_types const &rhs ) {
lhs << typeid(H).name() << " " << print_types<T...>();
return lhs;
}
};

template< class T >
struct spectfun {
friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {
lhs << "unknown";
return lhs;
}
};

template< class R, class ... A >
struct spectfun< R (*)( A ... ) > {
friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {
lhs << "returns " << print_types<R>()
<< " takes " << print_types<A ...>();
return lhs;
}
};

template< class C, class R, class ... A >
struct spectfun< R (C::*)( A ... ) > {
friend ostream &operator<< ( ostream &lhs, spectfun const &rhs ) {
lhs << "member of " << print_types<C>() << ", " << spectfun<R (*)(A...)>();
return lhs;
}
};

template< class T >
struct getcall {
typedef decltype(&T::operator()) type;
};

int main() {
int counter = 0;

auto count = [=]( int ) mutable { return ++ counter; };

cerr << spectfun< getcall<decltype(count)>::type >() << endl;
}

输出:

member of Z4mainEUlvE_, returns i takes i

编辑: 看起来唯一的问题是指向某些闭包调用运算符的指针无法匹配 ptmf 模板模式。解决方法是声明 lambda 表达式 mutable。如果没有捕获并且只有(除了解决问题之外)似乎改变了调用运算符的常量,这是没有意义的。

template< class T >
struct getcall {
typedef decltype(&T::operator()) type;
static type const value;
};
template< class T >
typename getcall<T>::type const getcall<T>::value = &T::operator();

int main() {
auto id = []( int x ) mutable { return x; };
int (*idp)( int ) = id;
typedef decltype(id) idt;
int (idt::*idptmf)( int ) /* const */ = getcall< decltype(id) >::value;

cerr << spectfun< decltype(idp) >() << endl;
cerr << spectfun< decltype(idptmf) >() << endl;
cerr << spectfun< getcall<decltype(id)>::type >() << endl;

输出:

returns i takes i 
member of Z4mainEUliE0_ , returns i takes i
member of Z4mainEUliE0_ , returns i takes i

如果没有 mutable 和 const,spectfun 不会打印最后两个查询中的任何一个的签名。

关于c++ - 跨 C++0x 编译器的 lambda 特征不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2611357/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com