c++ - Cross-platform "auto" keyword usage in lambdas: integral_constant as function argument -
i develop cross-platform (linux , win) library. within use of following helper templated functions work tuples (as example):
#include <iostream> #include <string> #include <tuple> #include <utility> #include <type_traits> using namespace std; template <class f, size_t... is> constexpr void index_apply_impl1(const f &f, const index_sequence<is...>&) { int d[] = { 0, (f(integral_constant<size_t, is> {}), 0)... }; } template <size_t n, class f> constexpr void index_apply1(const f& f) { index_apply_impl1(f, make_index_sequence<n>{}); } template <class tuple, class f> constexpr void apply1(const tuple &t, const f &f) { index_apply1<tuple_size<tuple>{}>( [&](auto &is) { f(get<is>(t)); } ); } template <size_t n, class f> constexpr void apply_by_index1(const f &f) { index_apply1<n>( [&](auto &&is) { f(integral_constant<size_t, is> {}); }); } int main() { auto t = make_tuple("aaa", 1, 11.11); // not work gcc //apply1(t, [&](auto &v) { cout << v << endl;} ); apply_by_index1<tuple_size<decltype(t)>::value>([&](auto &&i) { cout << get<i>(t) << endl; }); }
this code compiled , works expected gcc 5.4 , 6.4, won't compiled ms build tools 2015 (ms vc++ 2017 version not checked yet). error vc++ compiler prints related "auto"-type argument "is" of lambdas in function "apply_by_index1". vc++ says:
zz.cpp(29): error c2975: '_val': invalid template argument 'std::integral_constant', expected compile-time constant expression
...
zz.cpp(38): error c2672: 'get': no matching overloaded function found zz.cpp(29): note: see reference function template instantiation 'auto main::::operator ()>(std::integral_constant &&) const' being compiled
zz.cpp(38): error c2975: '_idx': invalid template argument 'std::get', expected compile-time constant expression
... , on
is generaly possible implement such functions vc++ or did miss something? thoughts replacing lambdas functors still have not idea how implement (i'm not proffesional programmer)
i have no clang/llvm belive code should compiled clang of version >=4. right?
i can give @ least partial solution. still cannot use std::get inside lambda.
namespace detail { template <typename t, typename f, typename... ts, size_t... is> void apply1(t&& t, f&& f, std::index_sequence<is...>) { const int d[] = { 0, (f(std::get<is>(t)), 0)... }; } template <typename t, typename f, size_t... is> void apply_by_index1(t&& t, f&& f, std::index_sequence<is...>) { const int d[] = { 0, (f(is), 0)... }; } template <size_t i, typename... ts> constexpr auto create_element(ts&&... ts) { return std::make_tuple(std::get<i>(std::forward<ts>(ts))...); } template <typename... ts, size_t... is> constexpr auto merge(std::index_sequence<is...>, ts&&... ts) { return std::make_tuple(create_element<is>(std::forward<ts>(ts)...)...); } } template <typename t, typename f> void apply1(t&& t, f&& f) { detail::apply1(std::forward<t>(t), std::forward<f>(f), std::make_index_sequence<std::tuple_size<std::decay_t<t>>::value>()); } template <typename t, typename f> void apply_by_index1(t&& t, f&& f) { detail::apply_by_index1(std::forward<t>(t), std::forward<f>(f), std::make_index_sequence<std::tuple_size<std::decay_t<t>>::value>()); } template <typename t, typename... ts> constexpr auto merge(t&& t, ts&&... ts) { return detail::merge(std::make_index_sequence<std::tuple_size<std::decay_t<t>>::value>(), std::forward<t>(t), std::forward<ts>(ts)...); } int main() { const auto t1 = std::make_tuple("hallo ", "hallo ", "hallo "); const auto t2 = std::make_tuple("world", "jon", "peter"); const auto t3 = std::make_tuple("!", "!", "!"); const auto t4 = merge(t1, t2, t3); apply1(t4, [](const auto& e) { std::cout << std::get<0>(e) << std::get<1>(e) << std::get<2>(e) << std::endl; }); return 0; }
Comments
Post a Comment