广义lambda在c ++ 14中的奇怪行为

时间:2014-12-15 10:54:42

标签: c++ lambda functional-programming c++14

要将一系列函数(不同类型)及其标识存储在同一个容器中,然后通过它们的标识调用它们,我首先将一个通用lambda实现为“list”容器,然后打包标识和函数体在std :: pair中,将对存储在'list'中;

'list'的代码是

template< typename ... Args >
auto list( Args ... args )
{
    return [=]( auto func ){ return func( args... ); };
}

然后以这种方式定义'cons',插入新对

template< typename List_1, typename List_2 >
auto cons( List_1 list_1, List_2 list_2 )
{
    return list_1( [=]( auto ... args_1 ){ return list_2( [=]( auto ... args_2 ){ return list( args_2..., args_1...); } ); } ); 
}

但不幸的是,似乎这个“缺点”生成的“列表”无法正确保持对,请参阅此处的完整代码:

http://melpon.org/wandbox/permlink/fo9tQnObFM4cyNcV

然后我将'cons'改为

template< typename List_1, typename List_2 >
auto cons( List_1 list_1, List_2 list_2 )
{

    auto layer_1 = [=]( auto ... args_1 ) { return list_2(  [=]( auto ... args_2 ) { return list( args_1..., args_2... ); } ); };
    return list_1( layer_1 );
}

然后它可以工作,请看这里:

http://melpon.org/wandbox/permlink/GpXEkkfztdOxapIL

但这两个'缺点'的实现与我相同,有人可以解释一下这个问题吗?

编辑:

根据Yakk的建议,我纠正了错字并将代码修改为

template< typename ... Args >
auto list( Args ... args )
{
    return [=]( auto func ){ return func( args... ); };
}

#ifdef V1
template< typename List_1, typename List_2 >
auto cons( List_1 list_1, List_2 list_2 )
{
    auto layer_1 = [=]( auto ... args_1 ) { return list_2(  [=]( auto ... args_2 ) { return list( args_1..., args_2... ); } ); };
    return list_1( layer_1 );
}
#endif

#ifdef V2
template< typename List_1, typename List_2 >
auto cons( List_1 list_1, List_2 list_2 )
{
    return list_1( [=]( auto ... args_1 ){ return list_2( [=]( auto ... args_2 ){ return list( args_1..., args_2...); } ); } );
}
#endif

template< typename Func, typename List >
auto map( Func func, List the_list )
{
    return the_list( [=]( auto ... elems ){ return list( func(elems)... ); } );
}

#include <string>
#include <utility>
#include <type_traits>
#include <iostream> 
int main()
{
    auto mfl = cons( cons( list( std::make_pair( std::string{"f1"}, [](int i){ return i; } ) ),
                 list( std::make_pair( std::string{"f2"}, []( double x, double y){ return x*y; } ) ) ),
                 list( std::make_pair( std::string{"f3"}, [](std::string s){ return s+s; } ) ) );

    auto pair_printer = []( auto the_pair ) { std::cout << "id:" << the_pair.first << "\n"; return the_pair; };
    map( pair_printer, mfl );

    return 0;
}

然后在clang ++ v3.5和g ++ 4.9.2

上测试了上面的代码

使用clang ++ v3.5和第一个'cons'(V1)

clang++ -o tmp tmp.cc -std=c++1y -lc++ -lc++abi -DV1

输出正确:

id:f1
id:f2
id:f3

第二个'缺点'(V2)

clang++ -o tmp tmp.cc -std=c++1y -lc++ -lc++abi -DV2

输出很乱:

id:f1
id: 4S� 4S�
id:4S��4S��4S��S���
                            �S��
                                    84S��4S�

使用g ++ 4.9.2,两个版本都给出了预期的输出。

这是clang ++的错误吗?


多年后更新:这个奇怪的行为已在最新版本(clang 6.0.1)中得到纠正。

0 个答案:

没有答案