summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2015-03-26 11:48:09 -0300
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2015-04-14 01:06:57 -0300
commitce36f0be936f218d87055cf21b643ab327f07853 (patch)
treefde18f8d5e3e33b57583ba321e61e7f4a07de224
parent72604d49574dba6d540d631895facbbc9b12bb2f (diff)
eolain_cxx: Fix C++ support for new Eolian features
Added optional constructor methods for C++ Eolian wrappers. Changed the interface of wrappers' main constructors. If there are optional constructor methods they should be passed as variadic template argument at the end of the constructor. To support variadic template arguments, the optional "parent" parameter is now the first parameter and there is another constructor without the "parent" parameter. Checking for @optinal and @nullable attributes instead of @nonull. Now @nonull is the default, and eina::optional is only used when @optional or @nullable attribute is specified. The names of constructor methods no longer have the class name prefixed. Added unit tests for checking the binding of optional constructors. Added new .eo file to be used in the test. Changed the generated documentation of constructors. Changed the efl::eo::inherit accordingly, to address these new features. Now the constructor methods should be explicit called in the efl::eo::inherit constructor, which will receive them via variadic template arguments. Added another constructor to efl::eo::inherit for passing the parent object. Updated some tests and examples to follow the new interface. Removed some code that is no longer necessary. Also, fix Eolian C++ support for constructing properties. fix assertion when parsing constructing properties. Now if a property is a constructing property eolian_cxx will generate a constructor method that have the property name (without the "_set" suffix).
-rw-r--r--src/Makefile_Eolian_Cxx.am15
-rw-r--r--src/Makefile_Eolian_Cxx_Helper.am5
-rw-r--r--src/bin/eolian_cxx/convert.cc68
-rw-r--r--src/bin/eolian_cxx/eolian_wrappers.hh6
-rw-r--r--src/bindings/eo_cxx/eo_cxx_interop.hh21
-rw-r--r--src/bindings/eo_cxx/eo_inherit.hh26
-rw-r--r--src/bindings/eo_cxx/eo_inherit_bindings.hh192
-rw-r--r--src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc2
-rw-r--r--src/examples/eolian_cxx/eolian_cxx_inherit_01.cc4
-rw-r--r--src/examples/eolian_cxx/eolian_cxx_simple_01.cc4
-rw-r--r--src/lib/eolian_cxx/eo_types.hh17
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh184
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_generator.hh2
-rw-r--r--src/lib/eolian_cxx/grammar/inheritance_base_generator.hh68
-rw-r--r--src/lib/eolian_cxx/grammar/type_generator.hh2
-rw-r--r--src/tests/eolian_cxx/eolian_cxx_suite.cc2
-rw-r--r--src/tests/eolian_cxx/eolian_cxx_test_binding.cc58
-rw-r--r--src/tests/eolian_cxx/generic.c77
-rw-r--r--src/tests/eolian_cxx/generic.eo58
19 files changed, 444 insertions, 367 deletions
diff --git a/src/Makefile_Eolian_Cxx.am b/src/Makefile_Eolian_Cxx.am
index d086bff103..77a62e3639 100644
--- a/src/Makefile_Eolian_Cxx.am
+++ b/src/Makefile_Eolian_Cxx.am
@@ -70,33 +70,39 @@ tests/eolian_cxx/a.c \
70tests/eolian_cxx/b.c \ 70tests/eolian_cxx/b.c \
71tests/eolian_cxx/c.c \ 71tests/eolian_cxx/c.c \
72tests/eolian_cxx/d.c \ 72tests/eolian_cxx/d.c \
73tests/eolian_cxx/eolian_cxx_test_binding.cc \
73tests/eolian_cxx/eolian_cxx_test_callback.cc \ 74tests/eolian_cxx/eolian_cxx_test_callback.cc \
74tests/eolian_cxx/eolian_cxx_test_address_of.cc \ 75tests/eolian_cxx/eolian_cxx_test_address_of.cc \
75tests/eolian_cxx/eolian_cxx_test_wrapper.cc \ 76tests/eolian_cxx/eolian_cxx_test_wrapper.cc \
76tests/eolian_cxx/simple.c \ 77tests/eolian_cxx/simple.c \
78tests/eolian_cxx/generic.c \
77tests/eolian_cxx/eolian_cxx_test_inheritance.cc \ 79tests/eolian_cxx/eolian_cxx_test_inheritance.cc \
78tests/eolian_cxx/eolian_cxx_test_generate.cc 80tests/eolian_cxx/eolian_cxx_test_generate.cc
79 81
80tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_wrapper.$(OBJEXT): tests/eolian_cxx/callback.eo.hh 82tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_wrapper.$(OBJEXT): tests/eolian_cxx/callback.eo.hh
81tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_callback.$(OBJEXT): tests/eolian_cxx/callback.eo.hh 83tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_callback.$(OBJEXT): tests/eolian_cxx/callback.eo.hh
84tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_inheritance.$(OBJEXT): tests/eolian_cxx/simple.eo.hh
85tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_binding.$(OBJEXT): tests/eolian_cxx/generic.eo.hh
82tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_address_of.$(OBJEXT): tests/eolian_cxx/a.eo.hh tests/eolian_cxx/b.eo.hh tests/eolian_cxx/c.eo.hh tests/eolian_cxx/d.eo.hh 86tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_address_of.$(OBJEXT): tests/eolian_cxx/a.eo.hh tests/eolian_cxx/b.eo.hh tests/eolian_cxx/c.eo.hh tests/eolian_cxx/d.eo.hh
83 87
84tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-callback.$(OBJEXT): tests/eolian_cxx/callback.eo.c tests/eolian_cxx/callback.eo.h 88tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-callback.$(OBJEXT): tests/eolian_cxx/callback.eo.c tests/eolian_cxx/callback.eo.h
89tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-simple.$(OBJEXT): tests/eolian_cxx/simple.eo.c tests/eolian_cxx/simple.eo.h
90tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-generic.$(OBJEXT): tests/eolian_cxx/generic.eo.c tests/eolian_cxx/generic.eo.h
85tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-a.$(OBJEXT): tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h 91tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-a.$(OBJEXT): tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h
86tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-b.$(OBJEXT): tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h 92tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-b.$(OBJEXT): tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h
87tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-c.$(OBJEXT): tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h 93tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-c.$(OBJEXT): tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h
88tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-d.$(OBJEXT): tests/eolian_cxx/d.eo.c tests/eolian_cxx/d.eo.h 94tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-d.$(OBJEXT): tests/eolian_cxx/d.eo.c tests/eolian_cxx/d.eo.h
89 95
90tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-eolian_cxx_test_inheritance.$(OBJEXT): tests/eolian_cxx/simple.eo.hh
91
92tests/eolian_cxx/tests_eolian_cxx_eolian_cxx_suite-simple.$(OBJEXT): tests/eolian_cxx/simple.eo.c tests/eolian_cxx/simple.eo.h
93
94CLEANFILES += tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/callback.eo.c \ 96CLEANFILES += tests/eolian_cxx/callback.eo.hh tests/eolian_cxx/callback.eo.c \
95tests/eolian_cxx/callback.eo.h \ 97tests/eolian_cxx/callback.eo.h \
96tests/eolian_cxx/simple.eo.c \ 98tests/eolian_cxx/simple.eo.c \
97tests/eolian_cxx/simple.eo.h \ 99tests/eolian_cxx/simple.eo.h \
98tests/eolian_cxx/simple.eo.hh \ 100tests/eolian_cxx/simple.eo.hh \
99tests/eolian_cxx/simple.eo.impl.hh \ 101tests/eolian_cxx/simple.eo.impl.hh \
102tests/eolian_cxx/generic.eo.c \
103tests/eolian_cxx/generic.eo.h \
104tests/eolian_cxx/generic.eo.hh \
105tests/eolian_cxx/generic.eo.impl.hh \
100tests/eolian_cxx/a.eo.hh tests/eolian_cxx/a.eo.impl.hh tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h \ 106tests/eolian_cxx/a.eo.hh tests/eolian_cxx/a.eo.impl.hh tests/eolian_cxx/a.eo.c tests/eolian_cxx/a.eo.h \
101tests/eolian_cxx/b.eo.hh tests/eolian_cxx/b.eo.impl.hh tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h \ 107tests/eolian_cxx/b.eo.hh tests/eolian_cxx/b.eo.impl.hh tests/eolian_cxx/b.eo.c tests/eolian_cxx/b.eo.h \
102tests/eolian_cxx/c.eo.hh tests/eolian_cxx/c.eo.impl.hh tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h \ 108tests/eolian_cxx/c.eo.hh tests/eolian_cxx/c.eo.impl.hh tests/eolian_cxx/c.eo.c tests/eolian_cxx/c.eo.h \
@@ -125,6 +131,7 @@ endif
125 131
126EXTRA_DIST += tests/eolian_cxx/callback.eo \ 132EXTRA_DIST += tests/eolian_cxx/callback.eo \
127tests/eolian_cxx/simple.eo \ 133tests/eolian_cxx/simple.eo \
134tests/eolian_cxx/generic.eo \
128tests/eolian_cxx/a.eo \ 135tests/eolian_cxx/a.eo \
129tests/eolian_cxx/b.eo \ 136tests/eolian_cxx/b.eo \
130tests/eolian_cxx/c.eo \ 137tests/eolian_cxx/c.eo \
diff --git a/src/Makefile_Eolian_Cxx_Helper.am b/src/Makefile_Eolian_Cxx_Helper.am
index bb656c8f28..b754edf635 100644
--- a/src/Makefile_Eolian_Cxx_Helper.am
+++ b/src/Makefile_Eolian_Cxx_Helper.am
@@ -12,10 +12,7 @@ am__v_EOLCXX_0 = @echo " EOLCXX " $@;
12 12
13SUFFIXES += .eo.hh 13SUFFIXES += .eo.hh
14 14
15%.eo.hh: %.eo $(_EOLIAN_CXX_DEP) 15%.eo.impl.hh %.eo.hh: %.eo $(_EOLIAN_CXX_DEP)
16 $(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -o $@ $< 16 $(AM_V_EOLCXX)$(EOLIAN_CXX) $(EOLIAN_FLAGS) -o $@ $<
17 17
18%.eo.impl.hh: %.eo.hh $(_EOLIAN_CXX_DEP)
19 true $<
20
21CLEANFILES += $(BUILT_SOURCES) 18CLEANFILES += $(BUILT_SOURCES)
diff --git a/src/bin/eolian_cxx/convert.cc b/src/bin/eolian_cxx/convert.cc
index 22ee22f0e5..4d03c8f775 100644
--- a/src/bin/eolian_cxx/convert.cc
+++ b/src/bin/eolian_cxx/convert.cc
@@ -212,6 +212,20 @@ _convert_property_get_to_function(Eolian_Class const& klass,
212 return get_; 212 return get_;
213} 213}
214 214
215static efl::eolian::eo_function
216_convert_function(Eolian_Class const& klass, Eolian_Function const& func)
217{
218 return {
219 function_type(func),
220 function_scope(func),
221 function_name(func),
222 function_impl(func),
223 function_return_type(func),
224 _convert_eolian_parameters(func),
225 convert_comments_function(klass, func, eolian_cxx::method)
226 };
227}
228
215 229
216void 230void
217convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klass) 231convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klass)
@@ -276,32 +290,42 @@ convert_eolian_functions(efl::eolian::eo_class& cls, Eolian_Class const& klass)
276 , last; first != last; ++first) 290 , last; first != last; ++first)
277 { 291 {
278 Eolian_Function const& func = *first; 292 Eolian_Function const& func = *first;
279 Eolian_Function_Type const func_type = function_op_type(func);
280
281 if (!function_is_visible(func, func_type))
282 continue;
283 293
284 if (function_is_constructor(klass, func)) 294 if (function_is_visible(func, function_op_type(func)) &&
295 !function_is_constructor(klass, func))
285 { 296 {
286 cls.constructors.push_back({ 297 cls.functions.push_back(_convert_function(klass, func));
287 function_impl(func),
288 _convert_eolian_parameters(func),
289 convert_comments_function(klass, func)
290 });
291 }
292 else
293 {
294 cls.functions.push_back({
295 function_type(func),
296 function_scope(func),
297 function_name(func),
298 function_impl(func),
299 function_return_type(func),
300 _convert_eolian_parameters(func),
301 convert_comments_function(klass, func, eolian_cxx::method)
302 });
303 } 298 }
304 } 299 }
300 if (class_eo_name(klass) != "EO_BASE_CLASS")
301 for(efl::eina::iterator<const Eolian_Constructor> first ( ::eolian_class_constructors_get(&klass))
302 , last; first != last; ++first)
303 {
304 Eolian_Constructor const& ctor = *first;
305 Eolian_Function const& func = *(::eolian_constructor_function_get(&ctor));
306
307 efl::eolian::eo_function f;
308 if (::eolian_function_type_get(&func) != EOLIAN_PROPERTY)
309 f = _convert_function(klass, func);
310 else
311 f = _convert_property_set_to_function(klass, func);
312
313
314 (::eolian_constructor_is_optional(&ctor) ?
315 cls.optional_constructors :
316 cls.constructors
317 ).push_back({
318 function_name(func),
319 f.impl,
320 f.params,
321 f.comment
322 });
323 }
324
325 cls.all_constructors = cls.constructors;
326 cls.all_constructors.insert(cls.all_constructors.end(),
327 cls.optional_constructors.begin(), cls.optional_constructors.end());
328
305 for(efl::eina::iterator<const Eolian_Function> first ( ::eolian_class_functions_get(&klass, EOLIAN_PROPERTY)) 329 for(efl::eina::iterator<const Eolian_Function> first ( ::eolian_class_functions_get(&klass, EOLIAN_PROPERTY))
306 , last; first != last; ++first) 330 , last; first != last; ++first)
307 { 331 {
diff --git a/src/bin/eolian_cxx/eolian_wrappers.hh b/src/bin/eolian_cxx/eolian_wrappers.hh
index 5cad7976c0..5b6579ed34 100644
--- a/src/bin/eolian_cxx/eolian_wrappers.hh
+++ b/src/bin/eolian_cxx/eolian_wrappers.hh
@@ -375,10 +375,8 @@ parameter_type(Eolian_Function_Parameter const& parameter,
375 if (!type.front().binding.empty()) 375 if (!type.front().binding.empty())
376 type.front().binding.insert(0, "const "); 376 type.front().binding.insert(0, "const ");
377 } 377 }
378 if (::eolian_parameter_is_nonull(&parameter)) 378 type.is_optional = ::eolian_parameter_is_optional(&parameter) ||
379 { 379 ::eolian_parameter_is_nullable(&parameter);
380 type.is_nonull = true;
381 }
382 return type; 380 return type;
383} 381}
384 382
diff --git a/src/bindings/eo_cxx/eo_cxx_interop.hh b/src/bindings/eo_cxx/eo_cxx_interop.hh
index 08ca3005ba..ef3e9c73f5 100644
--- a/src/bindings/eo_cxx/eo_cxx_interop.hh
+++ b/src/bindings/eo_cxx/eo_cxx_interop.hh
@@ -6,10 +6,13 @@
6#include <tuple> 6#include <tuple>
7#include <utility> 7#include <utility>
8#include <type_traits> 8#include <type_traits>
9#include <initializer_list>
9 10
10#include <Eina.hh> 11#include <Eina.hh>
11#include <Eo.hh> 12#include <Eo.hh>
12 13
14#include "eo_concrete.hh"
15
13namespace efl { namespace eolian { 16namespace efl { namespace eolian {
14 17
15//// From C++ to C 18//// From C++ to C
@@ -443,6 +446,14 @@ Eina_Bool free_callback_calback(void* data, Eo* obj EINA_UNUSED
443 return EO_CALLBACK_CONTINUE; 446 return EO_CALLBACK_CONTINUE;
444} 447}
445 448
449template <typename... Fs>
450inline
451void register_ev_del_free_callback(Eo* eoptr, Fs&&... fs)
452{
453 std::initializer_list<int const> const v {(fs.register_ev_del_free_callback(eoptr), 0)...};
454 (void) v; (void) eoptr;
455}
456
446template <typename F> 457template <typename F>
447inline 458inline
448std::vector<F>& get_static_callback_vector() 459std::vector<F>& get_static_callback_vector()
@@ -459,6 +470,16 @@ F* alloc_static_callback(F&& f)
459 return &(get_static_callback_vector<F>().back()); 470 return &(get_static_callback_vector<F>().back());
460} 471}
461 472
473/// Miscellaneous
474
475template <typename... Fs>
476inline
477void call_ctors(Fs&&... fs)
478{
479 std::initializer_list<int const> const v {(fs(), 0)...};
480 (void) v;
481}
482
462} } // namespace efl { namespace eolian { 483} } // namespace efl { namespace eolian {
463 484
464#endif // EFL_EOLIAN_INTEROP_HH 485#endif // EFL_EOLIAN_INTEROP_HH
diff --git a/src/bindings/eo_cxx/eo_inherit.hh b/src/bindings/eo_cxx/eo_inherit.hh
index 734b6b6561..3138d1e9a9 100644
--- a/src/bindings/eo_cxx/eo_inherit.hh
+++ b/src/bindings/eo_cxx/eo_inherit.hh
@@ -13,16 +13,17 @@
13 13
14#include "eo_ops.hh" 14#include "eo_ops.hh"
15#include "eo_private.hh" 15#include "eo_private.hh"
16#include "eo_cxx_interop.hh"
16 17
17namespace efl { namespace eo { 18namespace efl { namespace eo {
18 19
19namespace detail { 20namespace detail {
20 21
21template <typename D, typename Args, typename... E, std::size_t... S> 22template <typename D, typename... E, std::size_t... S>
22Eo_Class const* create_class(eina::index_sequence<S...>); 23Eo_Class const* create_class(eina::index_sequence<S...>);
23 24
24template <typename Args, typename ... E> 25inline
25void inherit_constructor(void* this_, Args args); 26void inherit_constructor(void* this_);
26 27
27} 28}
28 29
@@ -67,23 +68,26 @@ struct inherit
67 /// 68 ///
68 typedef inherit<D, E...> inherit_base; 69 typedef inherit<D, E...> inherit_base;
69 70
71 //@{
70 /// @brief Class constructor. 72 /// @brief Class constructor.
71 /// 73 ///
72 /// @ref inherit has a "variadic" constructor implementation that 74 /// @ref inherit has a "variadic" constructor implementation that
73 /// allows from zero to EFL_MAX_ARGS heterogeneous parameters. 75 /// allows from zero to EFL_MAX_ARGS heterogeneous parameters.
74 /// 76 ///
75 template<typename... Args> 77 template<typename... Args>
76 inherit(Args&& ... args) 78 inherit(efl::eo::parent_type _p, Args&& ... args)
77 { 79 {
78 typedef std::tuple<typename std::remove_reference<Args>::type...> tuple_type; 80 _eo_cls = detail::create_class<D, E...> (eina::make_index_sequence<sizeof...(E)>());
79 _eo_cls = detail::create_class<D, tuple_type, E...> (eina::make_index_sequence<sizeof...(E)>()); 81 _eo_raw = eo_add_ref(_eo_cls, _p._eo_raw, detail::inherit_constructor(this), ::efl::eolian::call_ctors(args...));
80 _eo_raw = eo_add_ref 82 ::efl::eolian::register_ev_del_free_callback(_eo_raw, args...);
81 (_eo_cls, NULL,
82 detail::inherit_constructor
83 <tuple_type, E...>
84 (static_cast<void*>(this), tuple_type(std::forward<Args>(args)...)));
85 } 83 }
86 84
85 template<typename... Args>
86 inherit(Args&& ... args)
87 : inherit(::efl::eo::parent = nullptr, std::forward<Args>(args)...)
88 {}
89 //@}
90
87 /// @brief Class destructor. 91 /// @brief Class destructor.
88 /// 92 ///
89 ~inherit() 93 ~inherit()
diff --git a/src/bindings/eo_cxx/eo_inherit_bindings.hh b/src/bindings/eo_cxx/eo_inherit_bindings.hh
index 73fc2b1554..6022c1d305 100644
--- a/src/bindings/eo_cxx/eo_inherit_bindings.hh
+++ b/src/bindings/eo_cxx/eo_inherit_bindings.hh
@@ -12,46 +12,6 @@ namespace efl { namespace eo { namespace detail {
12 12
13/// @internal 13/// @internal
14/// 14///
15/// @brief Invokes the <em>EO C Constructor</em> that corresponds to the
16/// binded <em>EO C++ Class</em>.
17///
18/// @param T The corresponding <em>EO C++ Class</em>
19/// @param Args An heterogeneous list of constructor arguments
20///
21/// @param tag Used to instruct the compiler during compile-time which
22/// of the overloads should be invoked.
23/// @param eo A pointer to the <em>EO C Object</em> to be constructed.
24/// @param cls Unused.
25/// @param args An heterogenous vector containing the constructor
26/// arguments, in the correct order.
27///
28/// To ensure full reciprocity of the C++ binding there must exist one
29/// (and only one) implementation of @ref efl::eo::detail::call_constructor
30/// for each available <em>EO C++ Class</em> --- the implementations
31/// are differentiated by this unique specialization of
32/// @ref efl::eo::detail::tag for the first argument of
33/// @ref efl::eo::detail::call_constructor.
34///
35/// For example this is how the overload for @ref eo_simple is
36/// written as follows:
37///
38/// @dontinclude eo_simple.hh
39/// @skip call_constructor
40/// @until }
41///
42/// As you can see @c ::simple_constructor is called with a single
43/// argument in this case. Each EO Class has its own constructor
44/// prototype -- which can have different argument types as well as
45/// distinct number of arguments, etc. -- hence the need to specify a
46/// choice for every known <em>EO C++ Class</em>.
47///
48/// @see efl::eo::detail::tag
49///
50template <typename T, typename Args>
51void call_constructor(efl::eo::detail::tag<T> tag, Eo* eo, Eo_Class const* cls, Args args);
52
53/// @internal
54///
55/// @brief Sums up the number of <em>EO Operations</em> of each class 15/// @brief Sums up the number of <em>EO Operations</em> of each class
56/// passed as argument to the template. 16/// passed as argument to the template.
57/// 17///
@@ -73,132 +33,6 @@ struct operation_description_size<>
73 static const int value = 0; 33 static const int value = 0;
74}; 34};
75 35
76template <typename T>
77struct is_args_class : std::false_type
78{
79};
80
81template <typename T, typename Tuple>
82struct is_args_class<args_class<T, Tuple> >
83 : std::true_type
84{
85};
86
87template <typename Tuple>
88struct are_args_class;
89
90template <>
91struct are_args_class<std::tuple<> >
92 : std::true_type
93{
94};
95
96template <typename T0, typename... T>
97struct are_args_class<std::tuple<T0, T...> >
98 : std::integral_constant
99 <bool
100 , is_args_class<T0>::value
101 && are_args_class<std::tuple<T...> >::value
102 >
103{
104};
105
106template <typename T, typename Tuple>
107struct has_args_class : std::false_type
108{
109 typedef std::integral_constant<std::size_t, 0u> index;
110};
111
112template <typename T, typename Tuple, typename... Args>
113struct has_args_class<T, std::tuple<detail::args_class<T, Tuple>, Args...> >
114 : std::true_type
115{
116 typedef detail::args_class<T, Tuple> type;
117 typedef std::integral_constant<std::size_t, 0u> index;
118};
119
120template <typename T, typename T0, typename... Args>
121struct has_args_class<T, std::tuple<T0, Args...> >
122 : has_args_class<T, std::tuple<Args...> >
123{
124 typedef has_args_class<T, std::tuple<Args...> > base_type;
125 typedef std::integral_constant
126 <std::size_t, 1u + base_type::index::value> index;
127};
128
129/// @internal
130///
131/// @brief An auxiliary template-class used to select the correct
132/// implementation of @ref efl::eo::call_constructor for @p T with
133/// proper parameters and variadic size.
134///
135/// @param T An <em>EO C++ Class</em>.
136///
137template <typename T, std::size_t N>
138struct call_constructor_aux
139{
140 template <typename Args, typename P>
141 static void do_(Args const&, Eo* eo, Eo_Class const* cls
142 , P, typename std::enable_if<!P::value>::type* = 0)
143 {
144 call_constructor(tag<T>(), eo, cls, args_class<T, std::tuple<> >(std::tuple<>()));
145 }
146
147 template <typename Args, typename P>
148 static void do_(Args const& args, Eo* eo, Eo_Class const* cls
149 , P, typename std::enable_if<P::value>::type* = 0)
150 {
151 call_constructor(tag<T>(), eo, cls, std::get<P::index::value>(args));
152 }
153
154 /// @internal
155 ///
156 /// @brief Invoke @def efl::eo::detail::call_constructor
157 /// implementation for the parent and each available extension.
158 ///
159 /// @param args An heterogenous sequence of arguments.
160 /// @param eo The opaque <em>EO Object</em>.
161 /// @param cls The opaque <em>EO Class</em>.
162 ///
163 template <typename Args>
164 static int do_(Args const& args, Eo* eo, Eo_Class const* cls)
165 {
166 static_assert(std::tuple_size<Args>::value <= N, "");
167 static_assert(are_args_class<Args>::value, "");
168 do_(args, eo, cls, has_args_class<T, Args>());
169 return 0;
170 }
171};
172
173template <typename T>
174struct call_constructor_aux<T, 1u>
175{
176 template <typename Args>
177 static void do_(Args const& args, Eo* eo, Eo_Class const* cls
178 , std::true_type)
179 {
180 static_assert(std::tuple_size<Args>::value == 1, "");
181 static_assert(std::is_same
182 <typename std::tuple_element<0u, Args>::type::class_type
183 , T>::value, "");
184 call_constructor(tag<T>(), eo, cls, std::get<0u>(args));
185 }
186
187 template <typename Args>
188 static void do_(Args const& args, Eo* eo, Eo_Class const* cls
189 , std::false_type)
190 {
191 call_constructor(tag<T>(), eo, cls, args_class<T, Args>(args));
192 }
193
194 template <typename Args>
195 static int do_(Args const& args, Eo* eo, Eo_Class const* cls)
196 {
197 do_(args, eo, cls, has_args_class<T, Args>());
198 return 0;
199 }
200};
201
202template <typename... Args> 36template <typename... Args>
203void call_varargs(Args...) 37void call_varargs(Args...)
204{ 38{
@@ -209,18 +43,14 @@ void call_varargs(Args...)
209/// @brief The procedure that actually is invoked when the constructor 43/// @brief The procedure that actually is invoked when the constructor
210/// of @c D is sought from the <em>EO Subsystem</em>. 44/// of @c D is sought from the <em>EO Subsystem</em>.
211/// 45///
212/// @param obj The opaque <em>EO Object</em>.
213/// @param self A pointer to @p obj's private data. 46/// @param self A pointer to @p obj's private data.
214/// @param this_ A void pointer to the opaque <em>EO Class</em> --- 47/// @param this_ A void pointer to the opaque <em>EO Class</em> ---
215/// passed as <em>user data</em>. 48/// passed as <em>user data</em>.
216/// @param args The arguments for the underlying constructor.
217/// 49///
218template <typename D, typename Args, typename... E> 50inline
219void inherit_constructor_impl(Eo* obj, Inherit_Private_Data* self, void* this_, Args args) 51void inherit_constructor_impl(Eo*, Inherit_Private_Data* self, void* this_)
220{ 52{
221 self->this_ = this_; 53 self->this_ = this_;
222 Eo_Class const* cls = static_cast<inherit<D, E...>*>(this_)->_eo_class();
223 detail::call_varargs(detail::call_constructor_aux<E, sizeof...(E)>::do_(args, obj, cls) ...);
224} 54}
225 55
226/// @internal 56/// @internal
@@ -231,16 +61,16 @@ void inherit_constructor_impl(Eo* obj, Inherit_Private_Data* self, void* this_,
231/// @param this_ The <em>user data</em> to be passed to the resolved function. 61/// @param this_ The <em>user data</em> to be passed to the resolved function.
232/// @param args An heterogeneous sequence of arguments. 62/// @param args An heterogeneous sequence of arguments.
233/// 63///
234template <typename Args, typename... E> 64EAPI inline
235EAPI void inherit_constructor(void* this_, Args args) 65void inherit_constructor(void* this_)
236{ 66{
237 typedef void (*func_t)(Eo *, void *, void*, Args); 67 typedef void (*func_t)(Eo *, void *, void*);
238 Eo_Op_Call_Data ___call; 68 Eo_Op_Call_Data ___call;
239 static Eo_Op op = EO_NOOP; 69 static Eo_Op op = EO_NOOP;
240 if ( op == EO_NOOP ) 70 if ( op == EO_NOOP )
241 op = _eo_api_op_id_get 71 op = _eo_api_op_id_get
242 (reinterpret_cast<void*> 72 (reinterpret_cast<void*>
243 (static_cast<void(*)(void*, Args)>(&detail::inherit_constructor<Args, E...>)), 73 (&detail::inherit_constructor),
244 ::eina_main_loop_is(), __FILE__, __LINE__); 74 ::eina_main_loop_is(), __FILE__, __LINE__);
245 if (!_eo_call_resolve("detail::inherit_constructor", op, &___call, 75 if (!_eo_call_resolve("detail::inherit_constructor", op, &___call,
246 ::eina_main_loop_is(), __FILE__, __LINE__)) 76 ::eina_main_loop_is(), __FILE__, __LINE__))
@@ -251,7 +81,7 @@ EAPI void inherit_constructor(void* this_, Args args)
251 } 81 }
252 func_t func = (func_t) ___call.func; 82 func_t func = (func_t) ___call.func;
253 EO_HOOK_CALL_PREPARE(eo_hook_call_pre, ""); 83 EO_HOOK_CALL_PREPARE(eo_hook_call_pre, "");
254 func(___call.obj, ___call.data, this_, args); 84 func(___call.obj, ___call.data, this_);
255 EO_HOOK_CALL_PREPARE(eo_hook_call_post, ""); 85 EO_HOOK_CALL_PREPARE(eo_hook_call_post, "");
256} 86}
257 87
@@ -289,7 +119,7 @@ operation_description_index<0u, E...>
289/// 119///
290/// @see efl::eo::inherit::inherit 120/// @see efl::eo::inherit::inherit
291/// 121///
292template <typename D, typename TupleArgs, typename... E, std::size_t ... S> 122template <typename D, typename... E, std::size_t ... S>
293Eo_Class const* create_class(eina::index_sequence<S...>) 123Eo_Class const* create_class(eina::index_sequence<S...>)
294{ 124{
295 static const Eo_Class* my_class = NULL; 125 static const Eo_Class* my_class = NULL;
@@ -299,14 +129,12 @@ Eo_Class const* create_class(eina::index_sequence<S...>)
299 op_descs[detail::operation_description_size<E...>::value].func = 129 op_descs[detail::operation_description_size<E...>::value].func =
300 reinterpret_cast<void*> 130 reinterpret_cast<void*>
301 ( 131 (
302 static_cast<void(*)(Eo*, Inherit_Private_Data*, void*, TupleArgs)> 132 &detail::inherit_constructor_impl
303 (&detail::inherit_constructor_impl<D, TupleArgs, E...>)
304 ); 133 );
305 op_descs[detail::operation_description_size<E...>::value].api_func = 134 op_descs[detail::operation_description_size<E...>::value].api_func =
306 reinterpret_cast<void*> 135 reinterpret_cast<void*>
307 ( 136 (
308 static_cast<void(*)(void*, TupleArgs)> 137 &detail::inherit_constructor
309 (&detail::inherit_constructor<TupleArgs, E...>)
310 ); 138 );
311 op_descs[detail::operation_description_size<E...>::value].op = EO_NOOP; 139 op_descs[detail::operation_description_size<E...>::value].op = EO_NOOP;
312 op_descs[detail::operation_description_size<E...>::value].op_type = EO_OP_TYPE_REGULAR; 140 op_descs[detail::operation_description_size<E...>::value].op_type = EO_OP_TYPE_REGULAR;
diff --git a/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc b/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc
index 8c41c0eab7..c9334bc5df 100644
--- a/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc
+++ b/src/examples/eolian_cxx/eolian_cxx_callbacks_01.cc
@@ -28,7 +28,7 @@ example_callbacks()
28{ 28{
29 int count = 0; 29 int count = 0;
30 efl::ecore::poller poller( 30 efl::ecore::poller poller(
31 poller.ecore_poller_constructor(ECORE_POLLER_CORE, 1, 31 poller.constructor(ECORE_POLLER_CORE, 1,
32 [&count, &poller] 32 [&count, &poller]
33 { 33 {
34 if (++count == 5) 34 if (++count == 5)
diff --git a/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc b/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc
index 0e6fce92f0..bdfa3ad19f 100644
--- a/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc
+++ b/src/examples/eolian_cxx/eolian_cxx_inherit_01.cc
@@ -17,7 +17,7 @@ struct ColourableCircle
17 : efl::eo::inherit<ColourableCircle, ::colourable> 17 : efl::eo::inherit<ColourableCircle, ::colourable>
18{ 18{
19 ColourableCircle(int rgb) 19 ColourableCircle(int rgb)
20 : inherit_base(efl::eo::args<::colourable>(rgb)) 20 : inherit_base(::colourable::rgb_24bits_constructor(rgb))
21 {} 21 {}
22 22
23 int colour_get() 23 int colour_get()
@@ -46,7 +46,7 @@ struct ColourableBar
46 : efl::eo::inherit<ColourableBar, ::colourablesquare> 46 : efl::eo::inherit<ColourableBar, ::colourablesquare>
47{ 47{
48 ColourableBar() 48 ColourableBar()
49 : inherit_base(efl::eo::args<::colourablesquare>(0)) 49 : inherit_base(::colourable::rgb_24bits_constructor(0))
50 {} 50 {}
51 51
52 int colour_get() 52 int colour_get()
diff --git a/src/examples/eolian_cxx/eolian_cxx_simple_01.cc b/src/examples/eolian_cxx/eolian_cxx_simple_01.cc
index 47b98cb4ce..04acebb138 100644
--- a/src/examples/eolian_cxx/eolian_cxx_simple_01.cc
+++ b/src/examples/eolian_cxx/eolian_cxx_simple_01.cc
@@ -19,13 +19,13 @@ main()
19 19
20 int r, g, b; 20 int r, g, b;
21 ::colourable obj1( 21 ::colourable obj1(
22 obj1.colourable_rgb_24bits_constructor(0x123456) 22 obj1.rgb_24bits_constructor(0x123456)
23 ); 23 );
24 obj1.colour_set(0xc0ffee); 24 obj1.colour_set(0xc0ffee);
25 obj1.composite_colour_get(&r, &g, &b); 25 obj1.composite_colour_get(&r, &g, &b);
26 26
27 ::colourablesquare obj2( 27 ::colourablesquare obj2(
28 obj2.colourablesquare_size_constructor(10) 28 obj2.size_constructor(10)
29 ); 29 );
30 obj2.composite_colour_set(r, g, b); 30 obj2.composite_colour_set(r, g, b);
31 obj2.size_set(11); 31 obj2.size_set(11);
diff --git a/src/lib/eolian_cxx/eo_types.hh b/src/lib/eolian_cxx/eo_types.hh
index b50e692ac1..987be69740 100644
--- a/src/lib/eolian_cxx/eo_types.hh
+++ b/src/lib/eolian_cxx/eo_types.hh
@@ -90,21 +90,21 @@ struct eolian_type_instance
90{ 90{
91 eolian_type_instance() 91 eolian_type_instance()
92 : is_out(false) 92 : is_out(false)
93 , is_nonull(false) 93 , is_optional(false)
94 , parts() 94 , parts()
95 {} 95 {}
96 96
97 eolian_type_instance(std::initializer_list<eolian_type> il, 97 eolian_type_instance(std::initializer_list<eolian_type> il,
98 bool is_out_ = false, 98 bool is_out_ = false,
99 bool is_nonull_ = false) 99 bool is_optional_ = false)
100 : is_out(is_out_) 100 : is_out(is_out_)
101 , is_nonull(is_nonull_) 101 , is_optional(is_optional_)
102 , parts(il) 102 , parts(il)
103 {} 103 {}
104 104
105 explicit eolian_type_instance(std::size_t size) 105 explicit eolian_type_instance(std::size_t size)
106 : is_out(false) 106 : is_out(false)
107 , is_nonull(false) 107 , is_optional(false)
108 , parts(size) 108 , parts(size)
109 {} 109 {}
110 110
@@ -115,7 +115,7 @@ struct eolian_type_instance
115 eolian_type const& front() const { return parts.front(); } 115 eolian_type const& front() const { return parts.front(); }
116 116
117 bool is_out; 117 bool is_out;
118 bool is_nonull; 118 bool is_optional;
119 eolian_type_container parts; 119 eolian_type_container parts;
120}; 120};
121 121
@@ -174,9 +174,9 @@ type_binding_requires_optional(eolian_type_instance const& type)
174} 174}
175 175
176inline bool 176inline bool
177type_is_nonull(eolian_type_instance const& type) 177type_is_optional(eolian_type_instance const& type)
178{ 178{
179 return type.is_nonull; 179 return type.is_optional;
180} 180}
181 181
182inline eolian_type 182inline eolian_type
@@ -254,6 +254,8 @@ struct eo_class
254 ancestors_container_type parents; 254 ancestors_container_type parents;
255 ancestors_container_type ancestors; 255 ancestors_container_type ancestors;
256 constructors_container_type constructors; 256 constructors_container_type constructors;
257 constructors_container_type optional_constructors;
258 constructors_container_type all_constructors;
257 functions_container_type functions; 259 functions_container_type functions;
258 events_container_type own_events; 260 events_container_type own_events;
259 events_container_type concrete_events; 261 events_container_type concrete_events;
@@ -270,6 +272,7 @@ struct eo_parameter
270struct eo_constructor 272struct eo_constructor
271{ 273{
272 std::string name; 274 std::string name;
275 std::string impl;
273 parameters_container_type params; 276 parameters_container_type params;
274 std::string comment; 277 std::string comment;
275}; 278};
diff --git a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
index 268855284d..5389a5d92d 100644
--- a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
+++ b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
@@ -109,8 +109,8 @@ inline std::ostream&
109operator<<(std::ostream& out, functors_constructor_methods const& x) 109operator<<(std::ostream& out, functors_constructor_methods const& x)
110{ 110{
111 constructors_container_type::const_iterator it, 111 constructors_container_type::const_iterator it,
112 first = x._cls.constructors.cbegin(), 112 first = x._cls.all_constructors.cbegin(),
113 last = x._cls.constructors.cend(); 113 last = x._cls.all_constructors.cend();
114 for (it = first; it != last; ++it) 114 for (it = first; it != last; ++it)
115 { 115 {
116 eo_constructor const& c = *it; 116 eo_constructor const& c = *it;
@@ -136,7 +136,7 @@ operator<<(std::ostream& out, functors_constructor_methods const& x)
136 << endl; 136 << endl;
137 137
138 // Struct constructor 138 // Struct constructor
139 out << tab(2) << constructor_functor_type_name(c) << "(" 139 out << tab(2) << "explicit " << constructor_functor_type_name(c) << "("
140 << parameters_declaration(c.params) << ")" 140 << parameters_declaration(c.params) << ")"
141 << parameters_cxx_generic(c.params, 141 << parameters_cxx_generic(c.params,
142 [](param_data d) 142 [](param_data d)
@@ -160,7 +160,24 @@ operator<<(std::ostream& out, functors_constructor_methods const& x)
160 // Struct operator() 160 // Struct operator()
161 out << tab(2) << "void operator()()" << endl 161 out << tab(2) << "void operator()()" << endl
162 << tab(2) << "{" << endl 162 << tab(2) << "{" << endl
163 << tab(3) << "::" << c.name << "(" << parameters_forward_to_c(c.params) << ");" << endl 163 << tab(3) << "::" << c.impl << "(" << parameters_forward_to_c(c.params) << ");" << endl
164 << tab(2) << "}" << endl;
165
166 // Register event to free allocated callbacks when the Eo* is deleted
167 out << tab(2) << "void register_ev_del_free_callback(Eo* _eoptr)" << endl
168 << tab(2) << "{" << endl
169 << tab(3) << "(void) _eoptr;" << endl
170 << parameters_cxx_generic(c.params,
171 [](param_data d)
172 {
173 if (d.is_cb)
174 d.out << tab(3)
175 << "eo_do(_eoptr," << endl
176 << tab(4) << "eo_event_callback_add(EO_EV_DEL, "
177 << "&::efl::eolian::free_callback_calback<"
178 << parameter_no_ref_type(d.type, d.name)
179 << ">, " << callback_tmp(d.name) << "));" << endl;
180 })
164 << tab(2) << "}" << endl; 181 << tab(2) << "}" << endl;
165 182
166 // Struct member variables 183 // Struct member variables
@@ -198,8 +215,8 @@ inline std::ostream&
198operator<<(std::ostream& out, constructor_method_function_declarations const& x) 215operator<<(std::ostream& out, constructor_method_function_declarations const& x)
199{ 216{
200 constructors_container_type::const_iterator it, 217 constructors_container_type::const_iterator it,
201 first = x._cls.constructors.cbegin(), 218 first = x._cls.all_constructors.cbegin(),
202 last = x._cls.constructors.cend(); 219 last = x._cls.all_constructors.cend();
203 for (it = first; it != last; ++it) 220 for (it = first; it != last; ++it)
204 { 221 {
205 eo_constructor const& c = *it; 222 eo_constructor const& c = *it;
@@ -216,8 +233,9 @@ operator<<(std::ostream& out, constructor_method_function_declarations const& x)
216 233
217 out << comment(c.comment, 1) 234 out << comment(c.comment, 1)
218 << template_parameters_declaration(c.params, 1) 235 << template_parameters_declaration(c.params, 1)
219 << tab(1) << constructor_functor_type_decl(c) << " " << c.name << "(" 236 << tab(1) << "static " << constructor_functor_type_decl(c)
220 << parameters_declaration(c.params) << ") const;" << endl << endl; 237 << " " << c.name << "("
238 << parameters_declaration(c.params) << ");" << endl << endl;
221 } 239 }
222 240
223 return out; 241 return out;
@@ -233,8 +251,8 @@ inline std::ostream&
233operator<<(std::ostream& out, constructor_method_function_definitions const& x) 251operator<<(std::ostream& out, constructor_method_function_definitions const& x)
234{ 252{
235 constructors_container_type::const_iterator it, 253 constructors_container_type::const_iterator it,
236 first = x._cls.constructors.cbegin(), 254 first = x._cls.all_constructors.cbegin(),
237 last = x._cls.constructors.cend(); 255 last = x._cls.all_constructors.cend();
238 for (it = first; it != last; ++it) 256 for (it = first; it != last; ++it)
239 { 257 {
240 eo_constructor const& c = *it; 258 eo_constructor const& c = *it;
@@ -249,7 +267,7 @@ operator<<(std::ostream& out, constructor_method_function_definitions const& x)
249 << "inline " << full_name(x._cls) 267 << "inline " << full_name(x._cls)
250 << "::" << constructor_functor_type_decl(c) << " " 268 << "::" << constructor_functor_type_decl(c) << " "
251 << full_name(x._cls, false) << "::" << c.name << "(" 269 << full_name(x._cls, false) << "::" << c.name << "("
252 << parameters_declaration(c.params) << ") const" << endl 270 << parameters_declaration(c.params) << ")" << endl
253 << "{" << endl 271 << "{" << endl
254 << tab(1) << "return " << constructor_functor_type_decl(c) << "(" 272 << tab(1) << "return " << constructor_functor_type_decl(c) << "("
255 << parameters_forward(c.params) << ");" << endl 273 << parameters_forward(c.params) << ");" << endl
@@ -280,24 +298,33 @@ operator<<(std::ostream& out, comment_constructor_with_constructor_methods const
280 if (x._cls.constructors.size()) 298 if (x._cls.constructors.size())
281 { 299 {
282 bool singular = (x._cls.constructors.size() == 1); 300 bool singular = (x._cls.constructors.size() == 1);
283 out << tab(2) << "Since this class have " << (singular ? "a " : "") << "constructor method" << (singular ? "" : "s") 301 out << tab(2) << "Since this class have " << (singular ? "a " : "")
302 << "necessary constructor method" << (singular ? "" : "s")
284 << ", you must call " << (singular ? "it" : "each one of them") << endl 303 << ", you must call " << (singular ? "it" : "each one of them") << endl
285 << tab(2) << "in the right place within this constructor parameters." << endl 304 << tab(2) << "in the right place within this constructor parameters." << endl
286 << endl; 305 << endl;
287 } 306 }
288 307
308 if (!x._cls.optional_constructors.empty())
309 {
310 out << tab(2) << "Optional constructors may be called in any combination as the" << endl
311 << tab(2) << "last parameters." << endl
312 << endl;
313 }
314
289 out << tab(2) << "Example:" << endl 315 out << tab(2) << "Example:" << endl
290 << tab(2) << "@code" << endl 316 << tab(2) << "@code" << endl
291 << tab(2) << full_name(x._cls, false) << " my_" << x._cls.name << "(" << endl; 317 << tab(2) << full_name(x._cls, false) << " my_" << x._cls.name << "(efl::eo::parent = parent_object";
292 318
293 for (eo_constructor const& c : x._cls.constructors) 319 for (eo_constructor const& c : x._cls.all_constructors)
294 out << tab(3) << "my_" << x._cls.name << "." << c.name << "(" << parameters_names(c.params) << ")," << endl; 320 out << "," << endl
321 << tab(3) << "my_" << x._cls.name << "." << c.name << "(" << parameters_names(c.params) << ")";
295 322
296 out << tab(3) << "efl::eo::parent = parent_object);" << endl 323 out << ");" << endl
297 << tab(2) << "@endcode" << endl 324 << tab(2) << "@endcode" << endl
298 << endl; 325 << endl;
299 326
300 for (eo_constructor const& c : x._cls.constructors) 327 for (eo_constructor const& c : x._cls.all_constructors)
301 out << tab(2) << "@see " << x._cls.name << "::" << c.name << endl; 328 out << tab(2) << "@see " << x._cls.name << "::" << c.name << endl;
302 out << tab(2) << "@see " << x._cls.name << "(Eo* eo)" << endl; 329 out << tab(2) << "@see " << x._cls.name << "(Eo* eo)" << endl;
303 330
@@ -307,8 +334,10 @@ operator<<(std::ostream& out, comment_constructor_with_constructor_methods const
307struct constructor_with_constructor_methods 334struct constructor_with_constructor_methods
308{ 335{
309 eo_class const& _cls; 336 eo_class const& _cls;
310 constructor_with_constructor_methods(eo_class const& cls) 337 bool _with_parent;
338 constructor_with_constructor_methods(eo_class const& cls, bool with_parent)
311 : _cls(cls) 339 : _cls(cls)
340 , _with_parent(with_parent)
312 {} 341 {}
313}; 342};
314 343
@@ -325,9 +354,7 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x)
325 cb_count += parameters_count_callbacks((*it).params); 354 cb_count += parameters_count_callbacks((*it).params);
326 } 355 }
327 356
328 out << comment_constructor_with_constructor_methods(x._cls); 357 if (cb_count != 0 || !x._cls.optional_constructors.empty())
329
330 if (cb_count != 0)
331 { 358 {
332 out << tab(1) << "template <"; 359 out << tab(1) << "template <";
333 for (unsigned i = 0; i != cb_count; ++i) 360 for (unsigned i = 0; i != cb_count; ++i)
@@ -336,14 +363,26 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x)
336 out << ", "; 363 out << ", ";
337 out << "typename F" << i; 364 out << "typename F" << i;
338 } 365 }
366 if (!x._cls.optional_constructors.empty())
367 {
368 if (cb_count != 0)
369 out << ", ";
370 out << "typename... FOpts";
371 }
339 out << ">" << endl; 372 out << ">" << endl;
340 } 373 }
341 374
342 out << tab(1) << x._cls.name << "("; 375 out << tab(1) << "explicit " << x._cls.name << "(";
376
377 if (x._with_parent)
378 out << "::efl::eo::parent_type _p";
379
343 { 380 {
344 unsigned cb_idx = 0; 381 unsigned cb_idx = 0;
345 for (it = first; it != last; ++it) 382 for (it = first; it != last; ++it)
346 { 383 {
384 if (x._with_parent || it != first)
385 out << ", ";
347 out << constructor_functor_type_name(*it); 386 out << constructor_functor_type_name(*it);
348 387
349 if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0) 388 if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
@@ -357,22 +396,54 @@ operator<<(std::ostream& out, constructor_with_constructor_methods const& x)
357 }) 396 })
358 << ">"; 397 << ">";
359 } 398 }
360 out << " _c" << (it-first) << ", "; 399 out << " _c" << (it-first);
361 } 400 }
362 assert(cb_idx == cb_count); 401 assert(cb_idx == cb_count);
363 } 402 }
364 out << "::efl::eo::parent_type _p = (::efl::eo::parent = nullptr))" << endl 403
365 << tab(2) << ": " << x._cls.name << "(_ctors_call("; 404 if (!x._cls.optional_constructors.empty())
405 {
406 if (x._with_parent || first != last)
407 out << ", ";
408 out << "FOpts&&... _opts";
409 }
410
411 out << ")" << endl
412 << tab(2) << ": " << x._cls.name << "(_ctors_call("
413 << (x._with_parent ? "_p" : "::efl::eo::parent = nullptr");
366 for (it = first; it != last; ++it) 414 for (it = first; it != last; ++it)
367 { 415 {
368 out << "_c" << (it-first) << ", "; 416 out << ", _c" << (it-first);
369 } 417 }
370 out << "_p))" << endl 418 if (!x._cls.optional_constructors.empty())
371 << tab(1) << "{}" << endl << endl; 419 {
420 out << ", std::forward<FOpts>(_opts)...";
421 }
422 out << "))" << endl
423 << tab(1) << "{}" << endl;
372 424
373 return out; 425 return out;
374} 426}
375 427
428struct constructors_with_constructor_methods
429{
430 eo_class const& _cls;
431 constructors_with_constructor_methods(eo_class const& cls)
432 : _cls(cls)
433 {}
434};
435
436inline std::ostream&
437operator<<(std::ostream& out, constructors_with_constructor_methods const& x)
438{
439 out << tab(1) << "//@{" << endl
440 << comment_constructor_with_constructor_methods(x._cls)
441 << constructor_with_constructor_methods(x._cls, true) << endl
442 << constructor_with_constructor_methods(x._cls, false)
443 << tab(1) << "//@}" << endl << endl;
444 return out;
445}
446
376struct constructor_eo 447struct constructor_eo
377{ 448{
378 eo_class const& _cls; 449 eo_class const& _cls;
@@ -460,24 +531,31 @@ operator<<(std::ostream& out, function_call_constructor_methods const& x)
460 last = x._cls.constructors.cend(); 531 last = x._cls.constructors.cend();
461 for (it = first; it != last; ++it) 532 for (it = first; it != last; ++it)
462 { 533 {
463 unsigned param_cb_count = parameters_count_callbacks((*it).params); 534 cb_count += parameters_count_callbacks((*it).params);
464 for (unsigned i = 0; i != param_cb_count; ++i) 535 }
536 if (cb_count != 0 || !x._cls.optional_constructors.empty())
537 {
538 out << tab(1) << "template <";
539 for (unsigned i = 0; i != cb_count; ++i)
465 { 540 {
466 if(cb_count == 0) 541 if (i != 0)
467 out << tab(1) << "template <"; 542 out << ", ";
468 else 543 out << "typename F" << i;
544 }
545 if (!x._cls.optional_constructors.empty())
546 {
547 if (cb_count != 0)
469 out << ", "; 548 out << ", ";
470 out << "typename F" << cb_count++; 549 out << "typename... FOpts";
471 } 550 }
551 out << ">" << endl;
472 } 552 }
473 if (cb_count != 0)
474 out << ">" << endl;
475 553
476 unsigned cb_idx = 0; 554 unsigned cb_idx = 0;
477 out << tab(1) << "static Eo* _ctors_call("; 555 out << tab(1) << "static Eo* _ctors_call(::efl::eo::parent_type _p";
478 for (it = first; it != last; ++it) 556 for (it = first; it != last; ++it)
479 { 557 {
480 out << constructor_functor_type_name(*it); 558 out << ", " << constructor_functor_type_name(*it);
481 559
482 if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0) 560 if (cb_count != 0 && parameters_count_callbacks((*it).params) != 0)
483 { 561 {
@@ -490,39 +568,29 @@ operator<<(std::ostream& out, function_call_constructor_methods const& x)
490 }) 568 })
491 << ">"; 569 << ">";
492 } 570 }
493 out << " _c" << (it-first) << ", "; 571 out << " _c" << (it-first);
494 } 572 }
495 assert(cb_idx == cb_count); 573 assert(cb_idx == cb_count);
496 574
497 out << "::efl::eo::parent_type _p)" << endl 575 if (!x._cls.optional_constructors.empty())
576 out << ", FOpts&&... _opts";
577
578 out << ")" << endl
498 << tab(1) << "{" << endl 579 << tab(1) << "{" << endl
499 << tab(2) << "Eo* _ret_eo = eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw"; 580 << tab(2) << "Eo* _ret_eo = eo_add_ref(" << x._cls.eo_name << ", _p._eo_raw";
500 for (it = first; it != last; ++it) 581 for (it = first; it != last; ++it)
501 { 582 {
502 out << ", _c" << (it-first) << "()"; 583 out << ", _c" << (it-first) << "()";
503 } 584 }
585 if (!x._cls.optional_constructors.empty())
586 out << ", ::efl::eolian::call_ctors(_opts...)";
504 out << ");" << endl << endl; 587 out << ");" << endl << endl;
505 588
506 cb_idx = 0;
507 for (it = first; it != last; ++it) 589 for (it = first; it != last; ++it)
508 { 590 out << tab(2) << "_c" << (it-first) << ".register_ev_del_free_callback(_ret_eo);" << endl;
509 if (parameters_count_callbacks((*it).params) == 0)
510 continue;
511 591
512 out << parameters_cxx_generic((*it).params, 592 if (!x._cls.optional_constructors.empty())
513 [&it, &first, &cb_idx](param_data d) 593 out << tab(2) << "::efl::eolian::register_ev_del_free_callback(_ret_eo, _opts...);" << endl;
514 {
515 if (d.is_cb)
516 d.out << tab(2)
517 << "eo_do(_ret_eo," << endl
518 << tab(3) << "eo_event_callback_add(EO_EV_DEL, "
519 << "&::efl::eolian::free_callback_calback<F" << cb_idx++
520 << ">, _c" << (it-first) << "." << callback_tmp(d.name)
521 << "));" << endl;
522 })
523 << endl;
524 }
525 assert(cb_idx == cb_count);
526 594
527 out << tab(2) << "return _ret_eo;" << endl 595 out << tab(2) << "return _ret_eo;" << endl
528 << tab(1) << "}" << endl << endl; 596 << tab(1) << "}" << endl << endl;
diff --git a/src/lib/eolian_cxx/grammar/eo_class_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_generator.hh
index c1d227cbcc..e1545fc875 100644
--- a/src/lib/eolian_cxx/grammar/eo_class_generator.hh
+++ b/src/lib/eolian_cxx/grammar/eo_class_generator.hh
@@ -230,7 +230,7 @@ eo_class_declarations_generator(std::ostream& out, eo_class const& cls)
230 << class_inheritance(cls) 230 << class_inheritance(cls)
231 << '{' << endl 231 << '{' << endl
232 << functors_constructor_methods(cls) 232 << functors_constructor_methods(cls)
233 << constructor_with_constructor_methods(cls) 233 << constructors_with_constructor_methods(cls)
234 << constructor_eo(cls) 234 << constructor_eo(cls)
235 << copy_constructor(cls) 235 << copy_constructor(cls)
236 << destructor(cls) 236 << destructor(cls)
diff --git a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh
index 11b8f2a29e..e134729aa4 100644
--- a/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh
+++ b/src/lib/eolian_cxx/grammar/inheritance_base_generator.hh
@@ -315,73 +315,6 @@ operator<<(std::ostream& out, inheritance_base_operations const& x)
315 return out; 315 return out;
316} 316}
317 317
318struct inheritance_call_constructor_arguments
319{
320 parameters_container_type const& _params;
321 inheritance_call_constructor_arguments(parameters_container_type const& params)
322 : _params(params)
323 {}
324};
325
326inline std::ostream&
327operator<<(std::ostream& out, inheritance_call_constructor_arguments const& x)
328{
329 parameters_container_type::size_type i, n = x._params.size();
330 for (i=0; i<n; i++)
331 {
332 if(i!=0) out << ", ";
333 out << "::efl::eolian::to_c(args.get<" << i << ">())";
334 }
335 return out;
336}
337
338struct inheritance_call_constructors
339{
340 eo_class const& _cls;
341 inheritance_call_constructors(eo_class const& cls) : _cls(cls) {}
342};
343
344inline std::ostream&
345operator<<(std::ostream& out, inheritance_call_constructors const& x)
346{
347 constructors_container_type::const_iterator it,
348 first = x._cls.constructors.begin(),
349 last = x._cls.constructors.end();
350 for (it = first; it != last; ++it)
351 {
352 eo_constructor const& ctor = *it;
353 out << "inline void" << endl
354 << "call_constructor(::efl::eo::detail::tag< "
355 << full_name(x._cls) << " >" << endl
356 << tab(5) << ", Eo* eo, Eo_Class const* cls EINA_UNUSED," << endl
357 << tab(5) << "::efl::eo::detail::args_class<"
358 << full_name(x._cls)
359 << ", ::std::tuple<"
360 << parameters_types(ctor.params)
361 << "> > const& args)" << endl
362 << "{" << endl
363 << tab(1) << "(void)args;" << endl
364 << tab(1)
365 << "eo_do_super(eo, cls, ::" << ctor.name
366 << "(" << inheritance_call_constructor_arguments(ctor.params)
367 << "));" << endl
368 << "}" << endl << endl;
369 }
370
371 out << "inline void" << endl
372 << "call_constructor(::efl::eo::detail::tag< "
373 << full_name(x._cls) << " >" << endl
374 << tab(5) << ", Eo* eo, Eo_Class const* cls EINA_UNUSED," << endl
375 << tab(5) << "::efl::eo::detail::args_class<"
376 << full_name(x._cls)
377 << ", ::std::tuple<::efl::eo::parent_type> > const& args)" << endl
378 << "{" << endl
379 << tab(1) << "eo_do(eo, ::eo_parent_set(args.get<0>()._eo_raw));" << endl
380 << "}" << endl << endl;
381
382 return out;
383}
384
385struct inheritance_eo_class_getter 318struct inheritance_eo_class_getter
386{ 319{
387 eo_class const& _cls; 320 eo_class const& _cls;
@@ -410,7 +343,6 @@ eo_inheritance_detail_generator(std::ostream& out, eo_class const& cls)
410 << inheritance_base_operations(cls) << endl 343 << inheritance_base_operations(cls) << endl
411 << inheritance_base_operations_size_scopes(cls) 344 << inheritance_base_operations_size_scopes(cls)
412 << inheritance_operations_description(cls) 345 << inheritance_operations_description(cls)
413 << inheritance_call_constructors(cls)
414 << inheritance_eo_class_getter(cls) 346 << inheritance_eo_class_getter(cls)
415 << "} } }" << endl; 347 << "} } }" << endl;
416} 348}
diff --git a/src/lib/eolian_cxx/grammar/type_generator.hh b/src/lib/eolian_cxx/grammar/type_generator.hh
index 193d2ea88a..de01890c98 100644
--- a/src/lib/eolian_cxx/grammar/type_generator.hh
+++ b/src/lib/eolian_cxx/grammar/type_generator.hh
@@ -110,7 +110,7 @@ operator<<(std::ostream& out, efl::eolian::grammar::reinterpret_type const& x)
110 { 110 {
111 if (x._type.is_out) 111 if (x._type.is_out)
112 res += "*"; 112 res += "*";
113 else if (!x._type.is_nonull && x._type.front().binding_requires_optional) 113 else if (x._type.is_optional && x._type.front().binding_requires_optional)
114 res = "::efl::eina::optional< " + res + " >"; 114 res = "::efl::eina::optional< " + res + " >";
115 } 115 }
116 116
diff --git a/src/tests/eolian_cxx/eolian_cxx_suite.cc b/src/tests/eolian_cxx/eolian_cxx_suite.cc
index cace098d79..7f8043914b 100644
--- a/src/tests/eolian_cxx/eolian_cxx_suite.cc
+++ b/src/tests/eolian_cxx/eolian_cxx_suite.cc
@@ -9,6 +9,7 @@ void eolian_cxx_test_generate(TCase* tc);
9void eolian_cxx_test_callback(TCase* tc); 9void eolian_cxx_test_callback(TCase* tc);
10void eolian_cxx_test_address_of(TCase* tc); 10void eolian_cxx_test_address_of(TCase* tc);
11void eolian_cxx_test_inheritance(TCase* tc); 11void eolian_cxx_test_inheritance(TCase* tc);
12void eolian_cxx_test_binding(TCase* tc);
12 13
13typedef struct _Eolian_Cxx_Test_Case Eolian_Cxx_Test_Case; 14typedef struct _Eolian_Cxx_Test_Case Eolian_Cxx_Test_Case;
14struct _Eolian_Cxx_Test_Case 15struct _Eolian_Cxx_Test_Case
@@ -24,6 +25,7 @@ static const Eolian_Cxx_Test_Case etc[] = {
24 { "Eolian-Cxx Callback", eolian_cxx_test_callback }, 25 { "Eolian-Cxx Callback", eolian_cxx_test_callback },
25 { "Eolian-Cxx Address_of", eolian_cxx_test_address_of }, 26 { "Eolian-Cxx Address_of", eolian_cxx_test_address_of },
26 { "Eolian-Cxx Inheritance", eolian_cxx_test_inheritance }, 27 { "Eolian-Cxx Inheritance", eolian_cxx_test_inheritance },
28 { "Eolian-Cxx Binding", eolian_cxx_test_binding },
27 { NULL, NULL } 29 { NULL, NULL }
28}; 30};
29 31
diff --git a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc
index ab3703c087..a6d8ebb310 100644
--- a/src/tests/eolian_cxx/eolian_cxx_test_binding.cc
+++ b/src/tests/eolian_cxx/eolian_cxx_test_binding.cc
@@ -1,2 +1,60 @@
1 1
2// test EFL++ generated bindings 2// test EFL++ generated bindings
3
4#ifdef HAVE_CONFIG_H
5# include <config.h>
6#endif
7
8#include <generic.eo.hh>
9
10#include <check.h>
11
12START_TEST(eolian_cxx_test_binding_constructor_only_required)
13{
14 efl::eo::eo_init i;
15
16 bool called1 = false;
17
18 generic g(
19 g.required_ctor_a(1),
20 g.required_ctor_b(std::bind([&called1] { called1 = true; }))
21 );
22
23 g.call_req_ctor_b_callback();
24 g.call_opt_ctor_b_callback();
25
26 fail_if(!called1);
27 fail_if(1 != g.req_ctor_a_value_get());
28}
29END_TEST
30
31START_TEST(eolian_cxx_test_binding_constructor_all_optionals)
32{
33 efl::eo::eo_init i;
34
35 bool called1 = false;
36 bool called2 = false;
37
38 generic g(
39 g.required_ctor_a(2),
40 g.required_ctor_b(std::bind([&called1] { called1 = true; })),
41 g.optional_ctor_a(3),
42 g.optional_ctor_b(std::bind([&called2] { called2 = true; }))
43 );
44
45 g.call_req_ctor_b_callback();
46 g.call_opt_ctor_b_callback();
47
48 fail_if(!called1);
49 fail_if(!called2);
50 fail_if(2 != g.req_ctor_a_value_get());
51 fail_if(3 != g.opt_ctor_a_value_get());
52}
53END_TEST
54
55void
56eolian_cxx_test_binding(TCase* tc)
57{
58 tcase_add_test(tc, eolian_cxx_test_binding_constructor_only_required);
59 tcase_add_test(tc, eolian_cxx_test_binding_constructor_all_optionals);
60}
diff --git a/src/tests/eolian_cxx/generic.c b/src/tests/eolian_cxx/generic.c
new file mode 100644
index 0000000000..1de4e5b6e1
--- /dev/null
+++ b/src/tests/eolian_cxx/generic.c
@@ -0,0 +1,77 @@
1
2#ifdef HAVE_CONFIG_H
3# include <config.h>
4#endif
5
6#include <Eo.h>
7#include <Ecore.h>
8
9#include "generic.eo.h"
10
11struct _Generic_Data
12{
13 int req_ctor_a_val;
14 Ecore_Cb req_ctor_b_cb;
15 void *req_ctor_b_data;
16 int opt_ctor_a_val;
17 Ecore_Cb opt_ctor_b_cb;
18 void *opt_ctor_b_data;
19};
20typedef struct _Generic_Data Generic_Data;
21
22#define MY_CLASS GENERIC_CLASS
23
24static void _generic_eo_base_constructor(Eo *obj, Generic_Data *pd)
25{
26 pd->req_ctor_a_val = 0;
27 pd->req_ctor_b_cb = NULL;
28 pd->req_ctor_b_data = NULL;
29 pd->opt_ctor_a_val = 0;
30 pd->opt_ctor_b_cb = NULL;
31 pd->opt_ctor_b_data = NULL;
32 eo_do_super(obj, MY_CLASS, eo_constructor());
33}
34
35static void _generic_required_ctor_a(Eo *obj EINA_UNUSED, Generic_Data *pd, int value)
36{
37 pd->req_ctor_a_val = value;
38}
39
40static void _generic_required_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data)
41{
42 cb(data);
43}
44
45static void _generic_optional_ctor_a(Eo *obj EINA_UNUSED, Generic_Data *pd, int value)
46{
47 pd->opt_ctor_a_val = value;
48}
49
50static void _generic_optional_ctor_b(Eo *obj EINA_UNUSED, Generic_Data *pd EINA_UNUSED, Ecore_Cb cb, void *data)
51{
52 cb(data);
53}
54
55static int _generic_req_ctor_a_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd)
56{
57 return pd->req_ctor_a_val;
58}
59
60static int _generic_opt_ctor_a_value_get(Eo *obj EINA_UNUSED, Generic_Data *pd)
61{
62 return pd->opt_ctor_a_val;
63}
64
65static void _generic_call_req_ctor_b_callback(Eo *obj EINA_UNUSED, Generic_Data *pd)
66{
67 if (pd->req_ctor_b_cb)
68 pd->req_ctor_b_cb(pd->req_ctor_b_data);
69}
70
71static void _generic_call_opt_ctor_b_callback(Eo *obj EINA_UNUSED, Generic_Data *pd)
72{
73 if (pd->opt_ctor_b_cb)
74 pd->opt_ctor_b_cb(pd->opt_ctor_b_data);
75}
76
77#include "generic.eo.c"
diff --git a/src/tests/eolian_cxx/generic.eo b/src/tests/eolian_cxx/generic.eo
new file mode 100644
index 0000000000..af21c02a0e
--- /dev/null
+++ b/src/tests/eolian_cxx/generic.eo
@@ -0,0 +1,58 @@
1class Generic (Eo.Base)
2{
3 legacy_prefix: null;
4 data: Generic_Data;
5 properties {
6 req_ctor_a_value {
7 get {
8 }
9 values {
10 int value;
11 }
12 }
13 opt_ctor_a_value {
14 get {
15 }
16 values {
17 int value;
18 }
19 }
20 }
21 methods {
22 required_ctor_a {
23 params {
24 @in int value;
25 }
26 }
27 required_ctor_b {
28 params {
29 @in Ecore_Cb cb;
30 @in void* data;
31 }
32 }
33 optional_ctor_a {
34 params {
35 @in int value;
36 }
37 }
38 optional_ctor_b {
39 params {
40 @in Ecore_Cb cb;
41 @in void* data;
42 }
43 }
44 call_req_ctor_b_callback {
45 }
46 call_opt_ctor_b_callback {
47 }
48 }
49 constructors {
50 .required_ctor_a;
51 .required_ctor_b;
52 .optional_ctor_a @optional;
53 .optional_ctor_b @optional;
54 }
55 implements {
56 Eo.Base.constructor;
57 }
58}