diff --git a/include/mp/proxy-types.h b/include/mp/proxy-types.h index 410de123..0221784c 100644 --- a/include/mp/proxy-types.h +++ b/include/mp/proxy-types.h @@ -38,15 +38,14 @@ struct StructField Struct& m_struct; // clang-format off - template auto get() const -> AUTO_RETURN(A::get(this->m_struct)) + template auto get() const -> decltype(A::get(this->m_struct)) { return A::get(this->m_struct); } template auto has() const -> typename std::enable_if::type { return A::getHas(m_struct); } template auto has() const -> typename std::enable_if::type { return A::has(m_struct); } template auto has() const -> typename std::enable_if::type { return true; } template auto want() const -> typename std::enable_if::type { return A::getWant(m_struct); } template auto want() const -> typename std::enable_if::type { return true; } - - template auto set(Args&&... args) const -> AUTO_RETURN(A::set(this->m_struct, std::forward(args)...)) - template auto init(Args&&... args) const -> AUTO_RETURN(A::init(this->m_struct, std::forward(args)...)) + template decltype(auto) set(Args&&... args) const { return A::set(this->m_struct, std::forward(args)...); } + template decltype(auto) init(Args&&... args) const { return A::init(this->m_struct, std::forward(args)...); } template auto setHas() const -> typename std::enable_if::type { return A::setHas(m_struct); } template auto setHas() const -> typename std::enable_if::type { } template auto setWant() const -> typename std::enable_if::type { return A::setWant(m_struct); } @@ -59,7 +58,7 @@ void CustomBuildField(TypeList<>, Priority<1>, ClientInvokeContext& invoke_context, Output&& output, - typename std::enable_if::value>::type* enable = nullptr) + typename std::enable_if::value>::type* enable = nullptr) { auto& connection = invoke_context.connection; auto& thread_context = invoke_context.thread_context; @@ -106,8 +105,10 @@ kj::Promise JoinPromises(kj::Promise&& prom1, kj::Promise&& prom2) return prom1.then(kj::mvCapture(prom2, [](kj::Promise prom2) { return prom2; })); } +//! PassField override for mp.Context arguments. Return asynchronously and call +//! function on other thread found in context. template -auto PassField(TypeList<>, ServerContext& server_context, const Fn& fn, const Args&... args) -> +auto PassField(Priority<1>, TypeList<>, ServerContext& server_context, const Fn& fn, Args&&... args) -> typename std::enable_if< std::is_same::value, kj::Promise>::type @@ -521,7 +522,7 @@ struct ProxyCallFn InvokeContext m_proxy; template - auto operator()(CallParams&&... params) -> AUTO_RETURN(this->m_proxy->call(std::forward(params)...)) + decltype(auto) operator()(CallParams&&... params) { return this->m_proxy->call(std::forward(params)...); } }; template @@ -762,10 +763,10 @@ struct ListOutput<::capnp::List> size_t m_index; // clang-format off - auto get() const -> AUTO_RETURN(this->m_builder[this->m_index]) - auto init() const -> AUTO_RETURN(this->m_builder[this->m_index]) - template auto set(Arg&& arg) const -> AUTO_RETURN(static_cast(this->m_builder).set(m_index, std::forward(arg))) - template auto init(Arg&& arg) const -> AUTO_RETURN(static_cast(this->m_builder).init(m_index, std::forward(arg))) + decltype(auto) get() const { return this->m_builder[this->m_index]; } + decltype(auto) init() const { return this->m_builder[this->m_index]; } + template decltype(auto) set(Arg&& arg) const { return static_cast(this->m_builder).set(m_index, std::forward(arg)); } + template decltype(auto) init(Arg&& arg) const { return static_cast(this->m_builder).init(m_index, std::forward(arg)); } // clang-format on }; @@ -978,8 +979,9 @@ void CustomBuildField(TypeList local_type, BuildOne<0>(local_type, invoke_context, output.init(), value); } +//! PassField override for C++ pointer arguments. template -void PassField(TypeList, ServerContext& server_context, const Fn& fn, Args&&... args) +void PassField(Priority<1>, TypeList, ServerContext& server_context, const Fn& fn, Args&&... args) { const auto& params = server_context.call_context.getParams(); const auto& input = Make(params); @@ -1002,8 +1004,9 @@ void PassField(TypeList, ServerContext& server_context, const Fn& fn Make(results), param); } +//! PassField override for callable interface reference arguments. template -auto PassField(TypeList, ServerContext& server_context, Fn&& fn, Args&&... args) +auto PassField(Priority<1>, TypeList, ServerContext& server_context, Fn&& fn, Args&&... args) -> Require { // Just create a temporary ProxyClient if argument is a reference to an @@ -1051,8 +1054,9 @@ void MaybeSetWant(LocalTypes, Priority<0>, Args&&...) { } +//! Default PassField implementation calling MaybeReadField/MaybeBuildField. template -void DefaultPassField(TypeList, ServerContext& server_context, Fn&& fn, Args&&... args) +void PassField(Priority<0>, TypeList, ServerContext& server_context, Fn&& fn, Args&&... args) { InvokeContext& invoke_context = server_context; using ArgType = RemoveCvRef; @@ -1074,6 +1078,18 @@ void DefaultPassField(TypeList, ServerContext& server_context, Fn&& f Make(results), *param); } +//! Default PassField implementation for count(0) arguments, calling ReadField/BuildField +template +void PassField(Priority<0>, TypeList<>, ServerContext& server_context, const Fn& fn, Args&&... args) +{ + const auto& params = server_context.call_context.getParams(); + const auto& input = Make(params); + ReadField(TypeList<>(), server_context, input); + fn.invoke(server_context, std::forward(args)...); + auto&& results = server_context.call_context.getResults(); + BuildField(TypeList<>(), server_context, Make(results)); +} + template <> struct ProxyServer final : public virtual ThreadMap::Server { @@ -1103,18 +1119,6 @@ decltype(auto) CustomReadField(TypeList<>, invoke_context.connection.m_thread_map = input.get(); } -template -auto PassField(TypeList<>, ServerContext& server_context, const Fn& fn, Args&&... args) -> typename std::enable_if< - std::is_same::value>::type -{ - const auto& params = server_context.call_context.getParams(); - const auto& input = Make(params); - ReadField(TypeList<>(), server_context, input); - fn.invoke(server_context, std::forward(args)...); - auto&& results = server_context.call_context.getResults(); - BuildField(TypeList<>(), server_context, Make(results)); -} - template struct IterateFieldsHelper { @@ -1248,10 +1252,12 @@ struct ServerCall { // FIXME: maybe call call_context.releaseParams() template - auto invoke(ServerContext& server_context, TypeList<>, Args&&... args) const -> AUTO_RETURN( - ProxyServerMethodTraits::invoke( + decltype(auto) invoke(ServerContext& server_context, TypeList<>, Args&&... args) const + { + return ProxyServerMethodTraits::invoke( server_context, - std::forward(args)...)) + std::forward(args)...); + } }; struct ServerDestroy @@ -1299,16 +1305,12 @@ struct ServerExcept : Parent template void CustomPassField(); -// clang-format off +//! PassField override calling CustomPassField function, if it exists. template -auto CallPassField(Priority<2>, Args&&... args) -> AUTO_RETURN(CustomPassField(std::forward(args)...)); - -template -auto CallPassField(Priority<1>, Args&&... args) -> AUTO_RETURN(PassField(std::forward(args)...)); - -template -auto CallPassField(Priority<0>, Args&&... args) -> AUTO_RETURN(DefaultPassField(std::forward(args)...)); -// clang-format on +auto PassField(Priority<2>, Args&&... args) -> decltype(CustomPassField(std::forward(args)...)) +{ + return CustomPassField(std::forward(args)...); +}; template struct ServerField : Parent @@ -1318,13 +1320,15 @@ struct ServerField : Parent const Parent& parent() const { return *this; } template - auto invoke(ServerContext& server_context, ArgTypes, Args&&... args) const - -> AUTO_RETURN(CallPassField(Priority<2>(), + decltype(auto) invoke(ServerContext& server_context, ArgTypes, Args&&... args) const + { + return PassField(Priority<2>(), typename Split::First(), server_context, this->parent(), typename Split::Second(), - std::forward(args)...)) + std::forward(args)...); + } }; template diff --git a/include/mp/proxy.h b/include/mp/proxy.h index 602c4ae4..6c0645e7 100644 --- a/include/mp/proxy.h +++ b/include/mp/proxy.h @@ -163,8 +163,10 @@ struct ProxyMethodTraits::impl)> { template - static auto invoke(ServerContext& server_context, Args&&... args) -> AUTO_RETURN( - (server_context.proxy_server.m_impl.get()->*ProxyMethod::impl)(std::forward(args)...)) + static decltype(auto) invoke(ServerContext& server_context, Args&&... args) + { + return (server_context.proxy_server.m_impl.get()->*ProxyMethod::impl)(std::forward(args)...); + } }; //! Customizable (through template specialization) traits class used in generated ProxyClient implementations from diff --git a/include/mp/util.h b/include/mp/util.h index 6addb018..ccbea6c9 100644 --- a/include/mp/util.h +++ b/include/mp/util.h @@ -55,17 +55,6 @@ namespace mp { //! } //! }; -// C++11 workaround for C++14 auto return functions -// (http://en.cppreference.com/w/cpp/language/template_argument_deduction#auto-returning_functions) -#define AUTO_DO_RETURN(pre, x) \ - decltype(x) \ - { \ - pre; \ - return x; \ - } - -#define AUTO_RETURN(x) AUTO_DO_RETURN(, x) - //! Type holding a list of types. //! //! Example: @@ -102,7 +91,7 @@ struct ComposeFn Fn2&& fn2; template - auto operator()(Args&&... args) -> AUTO_RETURN(this->fn1(this->fn2(std::forward(args)...))) + decltype(auto) operator()(Args&&... args) { return this->fn1(this->fn2(std::forward(args)...)); } }; //! Bound function. See Bind() below. @@ -116,8 +105,10 @@ struct BoundFn, TypeList> Fn&& m_fn; template - auto operator()(BoundArgs&... bound_args, FreeArgs&&... free_args) - -> AUTO_RETURN(this->m_fn(bound_args..., std::forward(free_args)...)) + decltype(auto) operator()(BoundArgs&... bound_args, FreeArgs&&... free_args) + { + return this->m_fn(bound_args..., std::forward(free_args)...); + } }; //! Specialization of above for recursive case. @@ -130,7 +121,7 @@ struct BoundFn, TypeList> BoundFn(Fn& fn, BindArg& bind_arg, BindArgs&... bind_args) : Base{fn, bind_args...}, m_bind_arg(bind_arg) {} - // Use std::result_of instead of AUTO_RETURN to work around gcc bug + // Use std::result_of instead of decltype return to work around gcc bug // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83249 template auto operator()(BoundArgs&... bound_args, FreeArgs&&... free_args) -> @@ -167,7 +158,7 @@ struct BoundTupleFn { Fn& m_fn; template - auto operator()(Params&&... params) -> AUTO_RETURN(this->m_fn(std::forward_as_tuple(params...))) + decltype(auto) operator()(Params&&... params) { return this->m_fn(std::forward_as_tuple(params...)); } }; //! Bind tuple argument to function. Arguments passed to the returned function diff --git a/src/mp/gen.cpp b/src/mp/gen.cpp index 13071fba..c78d6ffa 100644 --- a/src/mp/gen.cpp +++ b/src/mp/gen.cpp @@ -240,12 +240,12 @@ void Generate(kj::StringPtr src_prefix, std::string cap = Cap(name); accessors << "struct " << cap << "\n"; accessors << "{\n"; - accessors << " template static auto get(S&& s) -> AUTO_RETURN(s.get" << cap << "())\n"; + accessors << " template static auto get(S&& s) -> decltype(s.get" << cap << "()) { return s.get" << cap << "(); }\n"; accessors << " template static bool has(S&& s) { return s.has" << cap << "(); }\n"; accessors << " template static void set(S&& s, A&& a) { s.set" << cap << "(std::forward(a)); }\n"; - accessors << " template static auto init(S&& s, A&&... a) -> AUTO_RETURN(s.init" - << cap << "(std::forward(a)...))\n"; + accessors << " template static decltype(auto) init(S&& s, A&&... a) { return s.init" + << cap << "(std::forward(a)...); }\n"; accessors << " template static bool getWant(S&& s) { return s.getWant" << cap << "(); }\n"; accessors << " template static void setWant(S&& s) { s.setWant" << cap << "(true); }\n"; accessors << " template static bool getHas(S&& s) { return s.getHas" << cap << "(); }\n"; @@ -317,8 +317,8 @@ void Generate(kj::StringPtr src_prefix, auto field_name = field.getProto().getName(); auto member_name = field_name; GetAnnotationText(field.getProto(), NAME_ANNOTATION_ID, &member_name); - inl << " static auto get(std::integral_constant) -> AUTO_RETURN(" - << "&" << proxied_class_type << "::" << member_name << ")\n"; + inl << " static decltype(auto) get(std::integral_constant) { return " + << "&" << proxied_class_type << "::" << member_name << "; }\n"; ++i; } inl << " static constexpr size_t fields = " << i << ";\n";