Last active
May 15, 2021 04:21
-
-
Save loliGothicK/fd40e066bd666f5a8a73d38391c6692a to your computer and use it in GitHub Desktop.
C++のパラメータパック基礎&パック展開テクニック ref: https://qiita.com/_EnumHack/items/677363eec054d70b298d
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename ...Args > | |
void func( Args ...args ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <typename... Args> | |
auto my_make_tuple(Args ...args) | |
-> std::tuple<Args...> // テンプレートパラメータパックの展開 | |
{ | |
return { args... }; // 関数パラメータパックの展開 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// テンプレートパラメータパックのパラメータすべてに | |
// const& を付加して | |
// パラメータパックArgsの全てのパラメータを、 | |
// constな左辺値参照として受け取る | |
template < typename ...Args > | |
void f( const Args&... args ) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <typename ...Args> | |
void f( Args&&... args ) { | |
hoge( std::forward<Args>(args)... ); // パラメータパックの拡張は後述 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename... Types> | |
struct Hoge { | |
static constexpr unsigned long long size = sizeof...(Types); | |
}; | |
int main(){ | |
static_assert( Hoge<>::size == 0 , "" ); | |
static_assert( Hoge<void,void,void>::size ==3 , "" ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
template < typename T > | |
T g(T a){ return a*a; } | |
template < typename... Args > | |
auto print( Args const&... args ){ | |
for(auto const& e : { args... }) | |
std::cout << e << std::endl; | |
} | |
template < typename... Args > | |
void f(Args... args){ | |
print( g(args)... ); // 全てのパラメータにgを適用してprintに渡す | |
} | |
int main(){ | |
f(1,2,3,4); | |
// output: | |
// 1 | |
// 4 | |
// 9 | |
// 16 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::tuple<Args...> tup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename...Types > | |
std::tuple<std::decay_t<Types>...> // 全ての型にstd::decay_tを適用 | |
make_tuple(Types&&... args){ | |
return std::tuple<std::decay_t<Types>...>{ std::forward<Types>(args)... }; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Args > | |
void f(Args... args); // <- ここ、パラメータパックはargs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Args > // <- もちろんここ、パラメータパックはArgs | |
struct Hoge {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < template < class... > class T > // <- こういうやつです | |
struct Hoge {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
f(args...); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Args > | |
void print_all(Args&&... args){ | |
// 実装 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::tuple<Args...> tup; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
my_make_tuple(1, 2, 3.0); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename ...Args > | |
void func( Args ...args ) {} | |
int main(){ | |
func( 1, 3.0, 'a' ); // OK func<int,double,char> | |
func(); // OK func<> | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
int arr[] = { args... }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print(args)... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Bases > | |
class Derived : Bases...; // <- ここ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print(args)... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Bases > | |
class Derived : Bases... { | |
Derived(Bases... bases) | |
: Bases(bases)... {} // <- ここ | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[](auto... args){ | |
return [args...](auto ){ | |
// ^~~~~~~ここ | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <typename... T> | |
struct A : T... { | |
using T::operator()...; // 受け取ったクラスのoperator()を全て使えるようにする | |
}; | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Args > | |
void print_all(Args&&... args){ | |
// 実装 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Pack > | |
void func(Pack... pack){ | |
// ... | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename T > | |
void print(T const& a){ | |
std::cout << a << std::endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
( pack op ... ) //(1) | |
( ... op pack ) //(2) | |
( pack op ... op init ) //(3) | |
( init op ... op pack ) //(4) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace std { | |
template <class T, T... I> | |
struct integer_sequence { | |
using value_type = T; | |
static constexpr size_t size() noexcept { return sizeof...(I); } | |
}; | |
} | |
namespace std { | |
template <size_t... I> | |
using index_sequence = integer_sequence<size_t, I...>; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(E + ...) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print_all(1,2,3); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
E_1 + (... + (E_{N-1} + E_N)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print(1), print(2), print(3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(... + E) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// OK | |
template < typename Head, typename... Tail> | |
struct Hoge {}; | |
// コンパイルエラー!パラメータパックは最後に置かなければならない | |
template < typename... Init, typename Last> | |
struct Fuga {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Args... = int, int, double |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(void(適用したい関数(args)),0)... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(((E_1 + E_2) + E_3 ) + ... ) + E_n |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
auto old_sum1(){ | |
return 0; | |
} | |
template<typename T1, typename... T> | |
auto old_sum1(T1 s, T... ts){ | |
return s + old_sum1(ts...); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename T, typename... Tail > | |
constexpr T old_sum2( T&& head, Tail&&... tail ){ | |
T result = head; | |
using swallow = std::initializer_list<int>; | |
(void)swallow{ (void(result += tail),0)... }; | |
return result; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename T, typename... Args2 > | |
static constexpr T eval( left_t<Indeces,T>... args1, Args2... args2) | |
// ↑ この部分。引数左側にTが展開されて残りを推論する |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<typename... T> | |
auto fold_sum_1(T... s){ | |
return (... + s); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <map> | |
#include <utility> | |
#include <tuple> | |
struct Point3D { | |
Point3D(int a, int b,int c) | |
: x{a}, y{b}, z{c} {} | |
int x; | |
int y; | |
int z; | |
}; | |
int main(){ | |
std::pair<Point3D, int> p1{ std::piecewise_construct, | |
std::forward_as_tuple( 1,2,3 ), | |
std::forward_as_tuple( 1 ) | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template<typename... T> | |
auto fold_sum_2(T... s){ | |
return (1 + ... + s); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <tuple> | |
#include <utility> | |
#include <iostream> | |
namespace cranberries { | |
namespace cranberries_magic { | |
template < typename Tuple, size_t ...I > | |
std::array<int,sizeof...(I)> | |
tuple_print_impl(Tuple&& t, std::index_sequence<I...>){ | |
return {{ (void( std::cout << std::get<I>(t) << std::endl ), 0)... }}; | |
} | |
} // ! namespace cranberries_magic | |
template < typename Tuple > | |
void tuple_print(Tuple&& t){ | |
cranberries_magic::tuple_print_impl(std::forward<Tuple>(t), | |
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}); | |
} | |
} // ! namespace cranberries | |
int main(){ | |
cranberries::tuple_print(std::make_tuple(1,2,3,4,5)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
+ - * / % ^ & | = < > << >> += -= *= /= %= ^= &= |= <<= >>= == != <= >= && || , .* ->* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename T > | |
T max( T const& a, T const& b ){ | |
return a < b ? b : a; | |
} | |
template < typename Head, typename... Tail > | |
auto max( Head&& head, Tail&&... tail ){ | |
return max( std::forward<Head>(head), max( std::forward<Tail>(tail...) ) ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <map> | |
#include <utility> | |
#include <tuple> | |
struct Point3D { | |
Point3D(int a, int b,int c) | |
: x{a}, y{b}, z{c} {} | |
int x; | |
int y; | |
int z; | |
}; | |
int main(){ | |
std::pair<Point3D, int> p1{ std::piecewise_construct, | |
std::forward_as_tuple( 1,2,3 ), | |
std::forward_as_tuple( 1 ) | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <initializer_list> | |
#include <algorithm> | |
namespace cranberries { | |
template < typename T > | |
T max( std::initializer_list<T> il ){ | |
return *std::max_element(il.begin(), il.end()); | |
} | |
} // ! namespace cranberries | |
int main(){ | |
cranberries::max({1,2,3,4,5,6}); | |
std::max({1,2,3,4,5,6}); | |
// 可変長はないよ | |
//std::max(1,2,3,4,5,6); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < class... Args > | |
void print_all(Args&&... args){ | |
// 実装 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename T > | |
void print(T const& a){ | |
std::cout << a << std::endl; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
// OK | |
// 第1引数からパラメータパックTypesが推論される | |
template < typename ...Types, typename T > | |
void ok1(std::tuple<Types...>, T) | |
{} | |
// NG | |
// Argsの要素数をコンパイラが判断できない | |
// 引数の最後にパラメータパックを置かなければならない | |
template < typename ...Args, typename T > | |
void ng(Args..., T){} | |
// OK | |
// 引数の最後にパラメータパックが展開されているので可 | |
template < typename ...Args, typename T > | |
void ok2(T, Args...){} | |
int main(){ | |
// OK | |
// Args = [int,double,char], T = int | |
// tuple<int,double,char>からパラメータパックが推論される | |
ok1(std::make_tuple(1,1.0,'a'), 1); | |
// 推論できません | |
// ng1(1,2,3,4); | |
// OK | |
// T = int, Args = [int,int,int] | |
ok2(1,2,3,4); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
std::tuple<Args...> 👉 std::tuple<int, int, double> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NG | |
// 引数のどこまでがLeftでどこからRightなのかわからない | |
template < typename... Left, typename... Right > | |
void ng2(Left... left, Right... right){ | |
f(left...); | |
g(right...); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print(args)... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print_all(1,2,3); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
print(1), print(2), print(3) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(void(適用したい関数(args)),0)... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <initializer_list> | |
template < typename T > | |
void print(T const& a){ | |
std::cout << a << std::endl; | |
} | |
template < typename... Args > | |
void print_all(Args... args){ | |
using swallow = std::initializer_list<int>; | |
(void)swallow{ (void( print(args) ), 0)... }; | |
} | |
int main(){ | |
print_all(1,2,3,4,5,6); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <initializer_list> | |
#include <utility> | |
#include <type_traits> | |
namespace cranberries { | |
template < typename T, typename... Tail > | |
constexpr std::decay_t<T> max( T&& head, Tail&&... tail ){ | |
std::decay_t<T> result = head; | |
using swallow = std::initializer_list<int>; | |
(void)swallow{ (void(result = result < tail ? tail : result),0)... }; | |
return result; | |
} | |
} // ! namespace cranberries | |
int main(){ | |
constexpr auto x = cranberries::max(1,2,3,4,5); | |
static_assert(x==5,""); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace std { | |
template <class T, T... I> | |
struct integer_sequence { | |
using value_type = T; | |
static constexpr size_t size() noexcept { return sizeof...(I); } | |
}; | |
} | |
namespace std { | |
template <size_t... I> | |
using index_sequence = integer_sequence<size_t, I...>; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace std { | |
template <class T, T N> | |
using make_integer_sequence = integer_sequence<T, 0, 1, …, N - 1>; | |
} | |
namespace std { | |
template <size_t N> | |
using make_index_sequence = make_integer_sequence<size_t, N>; | |
} | |
namespace std { | |
template <class... T> | |
using index_sequence_for = make_index_sequence<sizeof...(T)>; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <tuple> | |
#include <utility> | |
#include <iostream> | |
namespace cranberries { | |
namespace cranberries_magic { | |
template < typename Tuple, size_t ...I > | |
std::array<int,sizeof...(I)> | |
tuple_print_impl(Tuple&& t, std::index_sequence<I...>){ | |
return {{ (void( std::cout << std::get<I>(t) << std::endl ), 0)... }}; | |
} | |
} // ! namespace cranberries_magic | |
template < typename Tuple > | |
void tuple_print(Tuple&& t){ | |
cranberries_magic::tuple_print_impl(std::forward<Tuple>(t), | |
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}); | |
} | |
} // ! namespace cranberries | |
int main(){ | |
cranberries::tuple_print(std::make_tuple(1,2,3,4,5)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <array> | |
#include <utility> | |
namespace cranberries { | |
namespace cranberries_magic { | |
template < size_t, class T = void > | |
struct left{ | |
using type = T; | |
}; | |
template < size_t N, class T > | |
using left_t = typename left<N,T>::type; | |
template < class > | |
struct sum_impl; | |
template < size_t... Indeces > | |
struct sum_impl<std::index_sequence<Indeces...>> { | |
template < typename T, typename... Args2 > | |
static constexpr T eval( left_t<Indeces,T>... args1, Args2... args2){ | |
return sum_impl<std::make_index_sequence<sizeof...(args1)/2>>::template eval<T>(args1...) | |
+ sum_impl<std::make_index_sequence<sizeof...(args2)/2>>::template eval<T>(args2...); | |
} | |
}; | |
template <> | |
struct sum_impl<std::index_sequence<>> { | |
template < typename T, typename... Args2 > | |
static constexpr T eval( T arg ){ | |
return arg; | |
} | |
}; | |
} // ! namespace cranberries_magic | |
template < typename Head, typename... Tail > | |
constexpr auto sum(Head head, Tail... tail){ | |
return cranberries_magic::sum_impl< | |
std::make_index_sequence<(sizeof...(Tail)+1)/2> | |
>:: template eval<std::decay_t<Head>>(head, tail...); | |
} | |
} // ! namespace cranberries | |
int main(){ | |
constexpr auto x = cranberries::sum(1,2,3,4,5,6,7,8,9,10,11); // 66 | |
static_assert(x==66,""); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// テンプレートパラメータパックのパラメータすべてに | |
// const& を付加して | |
// パラメータパックArgsの全てのパラメータを、 | |
// constな左辺値参照として受け取る | |
template < typename ...Args > | |
void f( const Args&... args ) {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
args... = 1, 2, 3.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < size_t, class T=void > | |
struct left{ | |
using type = T; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename T, typename... Args2 > | |
static constexpr T eval( left_t<Indeces,T>... args1, Args2... args2) | |
// ↑ この部分。引数左側にTが展開されて残りを推論する |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <> | |
struct sum_impl<std::index_sequence<>> { | |
template < typename T, typename... Args2 > | |
static constexpr T eval( T arg ){ | |
return arg; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NG | |
// 引数のどこまでがLeftでどこからRightなのかわからない | |
template < typename... Left, typename... Right > | |
void ng2(Left... left, Right... right){ | |
f(left...); | |
g(right...); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
#include <utility> | |
#include <iostream> | |
#include <initializer_list> | |
namespace cranberries { | |
namespace cranberries_magic { | |
template <class F, class Tuple, std::size_t... I> | |
constexpr decltype(auto) apply_impl( F&& f, Tuple&& t, std::index_sequence<I...> ) | |
{ | |
return f(std::get<I>(t)...); | |
} | |
} // ! namespace cranberries_magic | |
template <class F, class Tuple> | |
constexpr decltype(auto) apply(F&& f, Tuple&& t) | |
{ | |
return cranberries_magic::apply_impl(std::forward<F>(f), std::forward<Tuple>(t), | |
std::make_index_sequence<std::tuple_size<std::decay_t<Tuple>>::value>{}); | |
} | |
} // ! namespace cranberries | |
template < typename T > | |
void print(T const& a){ | |
std::cout << " " << a; | |
} | |
template < typename... Args > | |
void f(Args... args) { | |
std::cout << "called f with :"; | |
using swallow = std::initializer_list<int>; | |
(void)swallow{ (void( print(args) ), 0)... }; | |
std::cout << std::endl; | |
} | |
template < typename... Args > | |
void g(Args... args) { | |
std::cout << "called g with :"; | |
using swallow = std::initializer_list<int>; | |
(void)swallow{ (void( print(args) ), 0)... }; | |
std::cout << std::endl; | |
} | |
// OK | |
// 引数のどこまでがLeft,どこからRightなのかが | |
// コンパイラにもわかるように | |
// tupleに固めて区切る | |
template < typename... Left, typename... Right > | |
void ok( std::tuple<Left...> largs, std::tuple<Right...> rargs){ | |
// tupleの要素を関数に展開するためにapply関数をつかう | |
// もっとちゃんとしたものがC++17に採択決定している | |
cranberries::apply([](auto... args){ f(args...); }, largs); | |
cranberries::apply([](auto... args){ g(args...); }, rargs); | |
} | |
int main(){ | |
// forward_as_tupleで引数を完全転送して優勝! | |
ok( std::forward_as_tuple( 1,2,3 ), | |
std::forward_as_tuple( 4,5,6 ) ); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <map> | |
#include <utility> | |
#include <tuple> | |
struct Point3D { | |
Point3D(int a, int b,int c) | |
: x{a}, y{b}, z{c} {} | |
int x; | |
int y; | |
int z; | |
}; | |
int main(){ | |
std::pair<Point3D, int> p1{ std::piecewise_construct, | |
std::forward_as_tuple( 1,2,3 ), | |
std::forward_as_tuple( 1 ) | |
}; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <map> | |
#include <utility> | |
#include <tuple> | |
class Point3D { | |
public: | |
Point3D(int a, int b,int c) | |
: x_{a}, y_{b}, z_{c} {} | |
int x() const { return x_; } | |
int y() const { return y_; } | |
int z() const { return z_; } | |
private: | |
int x_; | |
int y_; | |
int z_; | |
}; | |
bool operator <(const Point3D& a, const Point3D& b){ | |
return std::forward_as_tuple(a.x(), a.y(), a.z()) < std::forward_as_tuple(b.x(), b.y(), b.z()); | |
} | |
int main(){ | |
std::map<Point3D, int> hash{}; | |
hash.emplace(std::piecewise_construct, | |
std::forward_as_tuple( 1,2,3 ), | |
std::forward_as_tuple( 1 ) | |
); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
reverse_apply(f, make_tuple(1,2,3,4)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
#include <type_traits> | |
#include <utility> | |
#include <initializer_list> | |
#include <iostream> | |
namespace cranberries { | |
namespace cranberries_magic { | |
template < class F | |
, class Tuple | |
, size_t... Indices | |
, size_t Last = std::tuple_size_v<std::decay_t<Tuple>>-1 > | |
constexpr decltype(auto) | |
reverse_apply_impl(F&& f, Tuple&& t, std::index_sequence<Indices...>){ | |
return f(std::get<Last-Indices>(t)...); | |
} | |
} | |
template < class F | |
, class Tuple > | |
constexpr decltype(auto) | |
reverse_apply(F&& f, Tuple&& t){ | |
return cranberries_magic::reverse_apply_impl(std::forward<F>(f) | |
, std::forward<Tuple>(t) | |
, std::make_index_sequence<std::tuple_size_v<std::decay_t<Tuple>>>{}); | |
} | |
} | |
int main(){ | |
auto println = [](auto&& head, auto&&... tail) -> void { | |
std::cout << head; | |
(void)std::initializer_list<int>{ | |
(void(std::cout << " " << tail), 0)... | |
}; | |
std::cout << std::endl; | |
}; | |
std::apply(println, std::make_tuple(1,2,3,"4")); | |
cranberries::reverse_apply(println, std::make_tuple(1,2,3,"4")); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template <typename ...Args> | |
void f( Args&&... args ) { | |
hoge( std::forward<Args>(args)... ); // パラメータパックの拡張は後述 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ args... } 👉 { 1, 2, 3.0 } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
template < typename ...Args > | |
void func( Args ...args ) {} | |
int main(){ | |
func( 1, 3.0, 'a' ); // OK func<int,double,char> | |
func(); // OK func<> | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// OK | |
template < typename Head, typename... Tail> | |
struct Hoge {}; | |
// コンパイルエラー!パラメータパックは最後に置かなければならない | |
template < typename... Init, typename Last> | |
struct Fuga {}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <tuple> | |
// OK | |
// 第1引数からパラメータパックTypesが推論される | |
template < typename ...Types, typename T > | |
void ok1(std::tuple<Types...>, T) | |
{} | |
// NG | |
// Argsの要素数をコンパイラが判断できない | |
// 引数の最後にパラメータパックを置かなければならない | |
template < typename ...Args, typename T > | |
void ng(Args..., T){} | |
// OK | |
// 引数の最後にパラメータパックが展開されているので可 | |
template < typename ...Args, typename T > | |
void ok2(T, Args...){} | |
int main(){ | |
// OK | |
// Args = [int,double,char], T = int | |
// tuple<int,double,char>からパラメータパックが推論される | |
ok1(std::make_tuple(1,1.0,'a'), 1); | |
// 推論できません | |
// ng1(1,2,3,4); | |
// OK | |
// T = int, Args = [int,int,int] | |
ok2(1,2,3,4); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment