Skip to content

Instantly share code, notes, and snippets.

@loliGothicK
Last active February 18, 2017 18:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save loliGothicK/196ac11095b48ca4b99ee0621306b70d to your computer and use it in GitHub Desktop.
Save loliGothicK/196ac11095b48ca4b99ee0621306b70d to your computer and use it in GitHub Desktop.
C++の間違った知識に振り回されないために ref: http://qiita.com/_EnumHack/items/ced694a5629d1b2210b7
// 変数がいっぱいある
int a{}, b{}, c{};
double d{}, e{}, f{};
std::string too_long_name_variable{};
// ラムダ式
auto result = [&a,&b,&c,&d,&e,&f,&too_long_name_variable](auto&& ...args){
// ...
// 何らかの処理
// ...
return result; // 計算結果結果を返す
}(1,2,3,4,5,5); // その場で呼び出す
やりたいこと
-> 可変長引数をバインドしておいて、後から指定した関数にわたす。
※その際、可変長引数はムーブしてバインドしたいとする。
[args... = std::move(args)...](){} // 可変長引数をムーブキャプチャ!
int main() {
// バインドする変数
hoge x{ 1 };
std::cout << "#1 : " << x.get() << std::endl;
/*
ラムダ式バージョン
*/
// #1 可変長引数をとる関数がラムダ式を返す
// #2 ラムダ式に可変長引数をバインドする
// #3 可変長引数を初期化キャプチャできないのでtupleに固めて初期化キャプチャ
// #4 ラムダ式が実行され、関数が指定されるとtupleを展開して関数に渡す
auto lambda = []( auto&&... args ) {
// #1
return [/* #2,#3 */t = std::make_tuple( std::move( args )... )]( auto&& func, auto&& ... ){
return cranberries::apply( func, t ); // #4
};
}(x);
// 呼び出し
lambda([]( auto&& head, auto&& ... ) {
std::cout << "#2 : " << head.get() << std::endl;
});
// バインドする変数
hoge y{ 2 };
std::cout << "#3 : " << y.get() << std::endl;
/*
std::bindバージョン
*/
// #1 可変長式数をとる関数がバインドオブジェクトを返す
// #2 bindに束縛させる関数はあとで指定する関数とその引数の両方を引数に取る関数(今回はラムダ式で書いた)
// #3 後で関数を指定するために第1引数はプレースホルダ
// #4 可変長引数をムーブしてバインドオブジェクトに束縛する
auto&& bind_expr = []( auto&& ...args ) {
// #1
return std::bind(
/* #2 */[]( auto&& func, auto&& ...args ) { return func( std::forward<decltype(args)>( args )... ); },
std::placeholders::_1, // #3
std::move( args )... ); // #4
}(y);
// 呼び出し
bind_expr(
[]( auto&& head, auto&& ... ) {
std::cout << "#4 : " << head.get() << std::endl;
});
}
#include <iostream>
#include <functional>
#include <vector>
#include <initializer_list>
#include <utility>
#include <tuple>
#include <memory>
#include "time_elapsed.hpp"
namespace cranberries {
template < typename F, typename Tuple, size_t... I >
decltype(auto) apply_impl( F&& f, Tuple&& t, std::index_sequence<I...> ) {
return f( std::forward<decltype(std::get<I>( t ))>( std::get<I>( t ) )... );
}
template < typename F, typename... Args >
decltype(auto) apply( F&& f, std::tuple<Args...> const& t ) {
return apply_impl( std::forward<F>( f ), t, std::index_sequence_for<Args...>{} );
}
}
class hoge {
public:
hoge() = default;
~hoge() = default;
hoge( hoge const& x ) : ptr{ std::make_unique<int>( *x.ptr ) } {
std::cout << "copy constructed" << std::endl;
}
hoge( hoge&& x ) : ptr{ std::move( x.ptr ) } {
std::cout << "move constructed" << std::endl;
}
hoge( int a ) : ptr{ std::make_unique<int>( a ) } {}
hoge& operator=( hoge const& x ) {
std::cout << "copy assigned" << std::endl;
*ptr = *x.ptr;
return *this;
}
hoge& operator=( hoge&& x ) {
std::cout << "move assigned" << std::endl;
ptr = std::move( x.ptr );
return *this;
}
auto* get() const {
return ptr.get();
}
decltype(auto) print( std::ostream& os ) const {
return os << *ptr;
}
private:
std::unique_ptr<int> ptr{};
};
decltype(auto) operator<< ( std::ostream& os, hoge const& x ) {
return x.print( os );
}
int main() {
hoge x{ 1 };
std::cout << "#1 : " << x.get() << std::endl;
CRANBERRIES_TIME_ELAPSED_MICRO(
auto lambda = []( auto&&... args ) {
return[t = std::make_tuple( std::move( args )... )]( auto&& func, auto&& ... ){
return cranberries::apply( func, t );
};
}(x);
lambda([]( auto&& head, auto&& ... ) {
std::cout << "#2 : " << head.get() << std::endl;
});
);
hoge y{ 2 };
std::cout << "#3 : " << y.get() << std::endl;
CRANBERRIES_TIME_ELAPSED_MICRO(
auto&& bind_expr = []( auto&& ...args ) {
return std::bind(
[]( auto&& func, auto&& ...args ) { return func( std::forward<decltype(args)>( args )... ); },
std::placeholders::_1,
std::move( args )... );
}(y);
bind_expr(
[]( auto&& head, auto&& ... ) {
std::cout << "#4 : " << head.get() << std::endl;
} );
);
}
#1 : 0000027810EEF2B0
move constructed
move constructed
#2 : 0000027810EEF2B0
1969[micro sec]
#3 : 0000027810EEF2D0
move constructed
#4 : 0000027810EEF2D0
1386[micro sec]
[t = std::make_tuple( std::move( args )... )]
#1 : 000002816499F3A0
move constructed
#2 : 000002816499F3A0
1437[micro sec]
#3 : 000002816499F4A0
move constructed
#4 : 000002816499F4A0
1444[micro sec]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment