summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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}