Merge remote-tracking branch 'upstream/develop' into develop

This commit is contained in:
draghan 2021-03-27 21:17:15 +01:00
commit 301f2e7061
16 changed files with 189 additions and 153 deletions

View File

@ -1,9 +1,9 @@
version: 6.1.x.{build} version: 6.1.x.{build}
image: image:
- Visual Studio 2017 - Visual Studio 2019
environment: environment:
matrix: matrix:
- VS_VERSION: "Visual Studio 15" - VS_VERSION: "Visual Studio 16"
build_script: build_script:
- cmd: >- - cmd: >-
mkdir build mkdir build

View File

@ -22,7 +22,7 @@ Note that ChaiScript cannot be used as a global / static object unless it is bei
### General ### General
``` ```cpp
chai.add(chaiscript::fun(&function_name), "function_name"); chai.add(chaiscript::fun(&function_name), "function_name");
chai.add(chaiscript::fun(&Class::method_name), "method_name"); chai.add(chaiscript::fun(&Class::method_name), "method_name");
chai.add(chaiscript::fun(&Class::member_name), "member_name"); chai.add(chaiscript::fun(&Class::member_name), "member_name");
@ -30,7 +30,7 @@ chai.add(chaiscript::fun(&Class::member_name), "member_name");
### Bound Member Functions ### Bound Member Functions
``` ```cpp
chai.add(chaiscript::fun(&Class::method_name, Class_instance_ptr), "method_name"); chai.add(chaiscript::fun(&Class::method_name, Class_instance_ptr), "method_name");
chai.add(chaiscript::fun(&Class::member_name, Class_instance_ptr), "member_name"); chai.add(chaiscript::fun(&Class::member_name, Class_instance_ptr), "member_name");
``` ```
@ -39,18 +39,18 @@ chai.add(chaiscript::fun(&Class::member_name, Class_instance_ptr), "member_name"
#### Preferred #### Preferred
``` ```cpp
chai.add(chaiscript::fun<ReturnType (ParamType1, ParamType2)>(&function_with_overloads), "function_name"); chai.add(chaiscript::fun<ReturnType (ParamType1, ParamType2)>(&function_with_overloads), "function_name");
``` ```
#### Alternative #### Alternative
``` ```cpp
chai.add(chaiscript::fun(std::static_cast<ReturnType (*)(ParamType1, ParamType2)>(&function_with_overloads)), "function_name"); chai.add(chaiscript::fun(std::static_cast<ReturnType (*)(ParamType1, ParamType2)>(&function_with_overloads)), "function_name");
``` ```
This overload technique is also used when exposing base member using derived type This overload technique is also used when exposing base member using derived type
``` ```cpp
struct Base struct Base
{ {
int data; int data;
@ -64,7 +64,7 @@ chai.add(chaiscript::fun(static_cast<int(Derived::*)>(&Derived::data)), "data");
### Lambda ### Lambda
``` ```cpp
chai.add( chai.add(
chaiscript::fun<std::function<std::string (bool)>>( chaiscript::fun<std::function<std::string (bool)>>(
[](bool type) { [](bool type) {
@ -75,7 +75,7 @@ chai.add(
### Constructors ### Constructors
``` ```cpp
chai.add(chaiscript::constructor<MyType ()>(), "MyType"); chai.add(chaiscript::constructor<MyType ()>(), "MyType");
chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType"); chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
``` ```
@ -84,7 +84,7 @@ chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc. It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
``` ```cpp
chai.add(chaiscript::user_type<MyClass>(), "MyClass"); chai.add(chaiscript::user_type<MyClass>(), "MyClass");
``` ```
@ -107,27 +107,27 @@ add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s);
Invoking a C++ type conversion possible with `static_cast` Invoking a C++ type conversion possible with `static_cast`
``` ```cpp
chai.add(chaiscript::type_conversion<T, bool>()); chai.add(chaiscript::type_conversion<T, bool>());
``` ```
Calling a user defined type conversion that takes a lambda Calling a user defined type conversion that takes a lambda
``` ```cpp
chai.add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { /* return converted thing */ })); chai.add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { /* return converted thing */ }));
``` ```
### Class Hierarchies ### Class Hierarchies
If you want objects to be convertable between base and derived classes, you must tell ChaiScritp about the relationship. If you want objects to be convertable between base and derived classes, you must tell ChaiScript about the relationship.
``` ```cpp
chai.add(chaiscript::base_class<Base, Derived>()); chai.add(chaiscript::base_class<Base, Derived>());
``` ```
If you have multiple classes in your inheritance graph, you will probably want to tell ChaiScript about all relationships. If you have multiple classes in your inheritance graph, you will probably want to tell ChaiScript about all relationships.
``` ```cpp
chai.add(chaiscript::base_class<Base, Derived>()); chai.add(chaiscript::base_class<Base, Derived>());
chai.add(chaiscript::base_class<Derived, MoreDerived>()); chai.add(chaiscript::base_class<Derived, MoreDerived>());
chai.add(chaiscript::base_class<Base, MoreDerived>()); chai.add(chaiscript::base_class<Base, MoreDerived>());
@ -168,7 +168,8 @@ chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overw
Namespaces will not be populated until `import` is called. Namespaces will not be populated until `import` is called.
This saves memory and computing costs if a namespace is not imported into every ChaiScript instance. This saves memory and computing costs if a namespace is not imported into every ChaiScript instance.
```
```cpp
chai.register_namespace([](chaiscript::Namespace& math) { chai.register_namespace([](chaiscript::Namespace& math) {
math["pi"] = chaiscript::const_var(3.14159); math["pi"] = chaiscript::const_var(3.14159);
math["sin"] = chaiscript::var(chaiscript::fun([](const double x) { return sin(x); })); }, math["sin"] = chaiscript::var(chaiscript::fun([](const double x) { return sin(x); })); },
@ -184,7 +185,7 @@ print(math.pi) // prints 3.14159
# Using STL # Using STL
ChaiScript recognize many types from STL, but you have to add specific instantiation yourself. ChaiScript recognize many types from STL, but you have to add specific instantiation yourself.
``` ```cpp
typedef std::vector<std::pair<int, std::string>> data_list; typedef std::vector<std::pair<int, std::string>> data_list;
data_list my_list{ make_pair(0, "Hello"), make_pair(1, "World") }; data_list my_list{ make_pair(0, "Hello"), make_pair(1, "World") };
chai.add(chaiscript::bootstrap::standard_library::vector_type<data_list>("DataList")); chai.add(chaiscript::bootstrap::standard_library::vector_type<data_list>("DataList"));
@ -202,7 +203,7 @@ chai.eval(R"_(
## General ## General
``` ```cpp
chai.eval("print(\"Hello World\")"); chai.eval("print(\"Hello World\")");
chai.eval(R"(print("Hello World"))"); chai.eval(R"(print("Hello World"))");
``` ```
@ -213,13 +214,13 @@ Returns values are of the type `Boxed_Value` which is meant to be opaque to the
### Prefered ### Prefered
``` ```cpp
chai.eval<double>("5.3 + 2.1"); // returns 7.4 as a C++ double chai.eval<double>("5.3 + 2.1"); // returns 7.4 as a C++ double
``` ```
### Alternative ### Alternative
``` ```cpp
auto v = chai.eval("5.3 + 2.1"); auto v = chai.eval("5.3 + 2.1");
chai.boxed_cast<double>(v); // extracts double value from boxed_value and applies known conversions chai.boxed_cast<double>(v); // extracts double value from boxed_value and applies known conversions
chaiscript::boxed_cast<double>(v); // free function version, does not know about conversions chaiscript::boxed_cast<double>(v); // free function version, does not know about conversions
@ -227,7 +228,7 @@ chaiscript::boxed_cast<double>(v); // free function version, does not know about
### Converting Between Algebraic Types ### Converting Between Algebraic Types
``` ```cpp
chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with any number type chaiscript::Boxed_Number(chai.eval("5.3 + 2.1")).get_as<int>(); // works with any number type
// which is equivalent to, but much more automatic than: // which is equivalent to, but much more automatic than:
static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double static_cast<int>(chai.eval<double>("5.3+2.1")); // this version only works if we know that it's a double
@ -257,7 +258,7 @@ int main()
## Sharing Values ## Sharing Values
``` ```cpp
double &d = chai.eval("var i = 5.2; i"); // d is now a reference to i in the script double &d = chai.eval("var i = 5.2; i"); // d is now a reference to i in the script
std::shared_ptr<double> d = chai.eval("var i = 5.2; i"); // same result but reference counted std::shared_ptr<double> d = chai.eval("var i = 5.2; i"); // same result but reference counted
@ -267,7 +268,7 @@ chai.eval("print(i)"); // prints 3
## Catching Eval Errors ## Catching Eval Errors
``` ```cpp
try { try {
chai.eval("2.3 + \"String\""); chai.eval("2.3 + \"String\"");
} catch (const chaiscript::exception::eval_error &e) { } catch (const chaiscript::exception::eval_error &e) {
@ -277,7 +278,7 @@ try {
## Catching Errors Thrown From Script ## Catching Errors Thrown From Script
``` ```cpp
try { try {
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>()); chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
} catch (const double e) { } catch (const double e) {
@ -292,19 +293,19 @@ try {
## Sharing Functions ## Sharing Functions
``` ```cpp
auto p = chai.eval<std::function<std::string (double)>>("to_string"); auto p = chai.eval<std::function<std::string (double)>>("to_string");
p(5); // calls chaiscript's 'to_string' function, returning std::string("5") p(5); // calls chaiscript's 'to_string' function, returning std::string("5")
``` ```
Note: backtick treats operators as normal functions Note: backtick treats operators as normal functions
``` ```cpp
auto p = chai.eval<std::function<int (int, int)>>(`+`); auto p = chai.eval<std::function<int (int, int)>>(`+`);
p(5, 6); // calls chaiscript's '+' function, returning 11 p(5, 6); // calls chaiscript's '+' function, returning 11
``` ```
``` ```cpp
auto p = chai.eval<std::function<std::string (int, double)>>("fun(x,y) { to_string(x) + to_string(y); }"); auto p = chai.eval<std::function<std::string (int, double)>>("fun(x,y) { to_string(x) + to_string(y); }");
p(3,4.2); // evaluates the lambda function, returning the string "34.2" to C++ p(3,4.2); // evaluates the lambda function, returning the string "34.2" to C++
``` ```
@ -344,7 +345,7 @@ while (some_condition()) { /* do something */ }
``` ```
// ranged for // ranged for
for (x : [1,2,3]) { print(i); } for (i : [1, 2, 3]) { print(i); }
``` ```
Each of the loop styles can be broken using the `break` statement. For example: Each of the loop styles can be broken using the `break` statement. For example:

View File

@ -271,7 +271,7 @@ namespace chaiscript {
template<typename ... T> template<typename ... T>
[[nodiscard]] auto make_vector(T && ... t) [[nodiscard]] auto make_vector(T &&... t) -> std::vector<std::common_type_t<std::decay_t<T>...>>
{ {
using container_type = using container_type =
std::vector<std::common_type_t<std::decay_t<T>...>>; std::vector<std::common_type_t<std::decay_t<T>...>>;

View File

@ -185,7 +185,9 @@ namespace chaiscript
return const_var(c_lhs * c_rhs); return const_var(c_lhs * c_rhs);
case Operators::Opers::difference: case Operators::Opers::difference:
return const_var(c_lhs - c_rhs); return const_var(c_lhs - c_rhs);
} default:
break;
}
if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) { if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
@ -203,7 +205,9 @@ namespace chaiscript
return const_var(c_lhs | c_rhs); return const_var(c_lhs | c_rhs);
case Operators::Opers::bitwise_xor: case Operators::Opers::bitwise_xor:
return const_var(c_lhs ^ c_rhs); return const_var(c_lhs ^ c_rhs);
} default:
break;
}
} }
if (t_lhs) { if (t_lhs) {
@ -224,7 +228,9 @@ namespace chaiscript
case Operators::Opers::assign_difference: case Operators::Opers::assign_difference:
*t_lhs -= c_rhs; *t_lhs -= c_rhs;
return t_bv; return t_bv;
} default:
break;
}
if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) { if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
switch (t_oper) { switch (t_oper) {
@ -247,7 +253,9 @@ namespace chaiscript
case Operators::Opers::assign_bitwise_xor: case Operators::Opers::assign_bitwise_xor:
*t_lhs ^= c_rhs; *t_lhs ^= c_rhs;
return t_bv; return t_bv;
} default:
break;
}
} }
} }
@ -299,7 +307,9 @@ namespace chaiscript
case Operators::Opers::pre_decrement: case Operators::Opers::pre_decrement:
--(*lhs); --(*lhs);
return t_lhs; return t_lhs;
} default:
break;
}
} }
switch (t_oper) { switch (t_oper) {
@ -307,13 +317,17 @@ namespace chaiscript
return const_var(-c_lhs); return const_var(-c_lhs);
case Operators::Opers::unary_plus: case Operators::Opers::unary_plus:
return const_var(+c_lhs); return const_var(+c_lhs);
} default:
break;
}
if constexpr (!std::is_floating_point_v<std::decay_t<decltype(c_lhs)>>) { if constexpr (!std::is_floating_point_v<std::decay_t<decltype(c_lhs)>>) {
switch (t_oper) { switch (t_oper) {
case Operators::Opers::bitwise_complement: case Operators::Opers::bitwise_complement:
return const_var(~c_lhs); return const_var(~c_lhs);
} default:
break;
}
} }
throw chaiscript::detail::exception::bad_any_cast(); throw chaiscript::detail::exception::bad_any_cast();

View File

@ -1303,8 +1303,8 @@ namespace chaiscript
const auto lhssize = lhsparamtypes.size(); const auto lhssize = lhsparamtypes.size();
const auto rhssize = rhsparamtypes.size(); const auto rhssize = rhsparamtypes.size();
constexpr const auto boxed_type = user_type<Boxed_Value>(); const auto boxed_type = user_type<Boxed_Value>();
constexpr const auto boxed_pod_type = user_type<Boxed_Number>(); const auto boxed_pod_type = user_type<Boxed_Number>();
for (size_t i = 1; i < lhssize && i < rhssize; ++i) for (size_t i = 1; i < lhssize && i < rhssize; ++i)
{ {

View File

@ -39,9 +39,9 @@ namespace chaiscript
{ {
} }
Ret call(const Function_Params &params, const Type_Conversions_State &t_state) Ret call(const chaiscript::Function_Params &params, const Type_Conversions_State &t_state)
{ {
if constexpr (std::is_arithmetic_v<Ret>) { if constexpr (std::is_arithmetic_v<Ret> && !std::is_same_v<std::remove_cv_t<std::remove_reference_t<Ret>>, bool>) {
return Boxed_Number(dispatch::dispatch(m_funcs, params, t_state)).get_as<Ret>(); return Boxed_Number(dispatch::dispatch(m_funcs, params, t_state)).get_as<Ret>();
} else if constexpr (std::is_same_v<void, Ret>) { } else if constexpr (std::is_same_v<void, Ret>) {
dispatch::dispatch(m_funcs, params, t_state); dispatch::dispatch(m_funcs, params, t_state);
@ -57,11 +57,11 @@ namespace chaiscript
if (m_conversions) { if (m_conversions) {
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves()); Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
return call(Function_Params{params}, state); return call(chaiscript::Function_Params{params}, state);
} else { } else {
Type_Conversions conv; Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves()); Type_Conversions_State state(conv, conv.conversion_saves());
return call(Function_Params{params}, state); return call(chaiscript::Function_Params{params}, state);
} }
} }

View File

@ -30,13 +30,13 @@ namespace chaiscript {
} }
explicit Function_Params(const std::vector<Boxed_Value> &vec) explicit Function_Params(const std::vector<Boxed_Value> &vec)
: m_begin(&vec.front()), m_end(&vec.front() + vec.size()) : m_begin(vec.empty() ? nullptr : &vec.front()), m_end(vec.empty() ? nullptr : &vec.front() + vec.size())
{ {
} }
template<size_t Size> template<size_t Size>
constexpr explicit Function_Params(const std::array<Boxed_Value, Size> &a) constexpr explicit Function_Params(const std::array<Boxed_Value, Size> &a)
: m_begin(std::begin(a)), m_end(std::end(a)) : m_begin(&a.front()), m_end(&a.front() + Size)
{ {
} }
@ -74,6 +74,13 @@ namespace chaiscript {
}; };
// Constructor specialization for array of size 0
template<>
constexpr Function_Params::Function_Params(const std::array<Boxed_Value, size_t{0}> & /* a */)
: m_begin(nullptr), m_end(nullptr)
{
}
} }

View File

@ -4,121 +4,142 @@
#include <type_traits> #include <type_traits>
namespace chaiscript::dispatch::detail { namespace chaiscript::dispatch::detail {
template<typename ... Param>
struct Function_Params
{
};
template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false> template<typename... Param>
struct Function_Signature { struct Function_Params
using Param_Types = Params; {
using Return_Type = Ret; };
constexpr static const bool is_object = IsObject;
constexpr static const bool is_member_object = IsMemberObject;
constexpr static const bool is_noexcept = IsNoExcept;
template<typename T>
constexpr Function_Signature(T &&) noexcept {}
constexpr Function_Signature() noexcept = default;
};
// Free functions template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false>
struct Function_Signature
{
using Param_Types = Params;
using Return_Type = Ret;
constexpr static const bool is_object = IsObject;
constexpr static const bool is_member_object = IsMemberObject;
constexpr static const bool is_noexcept = IsNoExcept;
template<typename T>
constexpr Function_Signature(T &&) noexcept {}
constexpr Function_Signature() noexcept = default;
};
template<typename Ret, typename ... Param> // Free functions
Function_Signature(Ret (*f)(Param...)) -> Function_Signature<Ret, Function_Params<Param...>>;
template<typename Ret, typename ... Param> template<typename Ret, typename... Param>
Function_Signature(Ret (*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Param...>, true>; Function_Signature(Ret (*f)(Param...))->Function_Signature<Ret, Function_Params<Param...>>;
// no reference specifier template<typename Ret, typename... Param>
Function_Signature(Ret (*f)(Param...) noexcept)->Function_Signature<Ret, Function_Params<Param...>, true>;
template<typename Ret, typename Class, typename ... Param> // no reference specifier
Function_Signature(Ret (Class::*f)(Param ...) volatile) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile noexcept) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) volatile)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile const) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) volatile noexcept)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile const noexcept) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) volatile const)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) ) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) volatile const noexcept)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...))->Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) const) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) noexcept)->Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) const noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) const)->Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
// & reference specifier template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param...) const noexcept)->Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> // & reference specifier
Function_Signature(Ret (Class::*f)(Param ...) volatile &) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile & noexcept) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) volatile &)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile const &) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) volatile &noexcept)->Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile const & noexcept) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) volatile const &)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) & ) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) volatile const &noexcept)->Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) & noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) &)->Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) const &) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) & noexcept)->Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) const & noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) const &)->Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
// && reference specifier template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param...) const &noexcept)->Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> // && reference specifier
Function_Signature(Ret (Class::*f)(Param ...) volatile &&) -> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile && noexcept) -> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) volatile &&)->Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile const &&) -> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) volatile &&noexcept)->Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) volatile const && noexcept) -> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) volatile const &&)->Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) &&) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) volatile const &&noexcept)->Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) && noexcept) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) &&)->Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) const &&) -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>; Function_Signature(Ret (Class::*f)(Param...) && noexcept)->Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>;
template<typename Ret, typename Class, typename ... Param> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)(Param ...) const && noexcept) -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, true, true>; Function_Signature(Ret (Class::*f)(Param...) const &&)->Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>;
template<typename Ret, typename Class> template<typename Ret, typename Class, typename... Param>
Function_Signature(Ret (Class::*f)) -> Function_Signature<Ret, Function_Params<Class &>, true, true, true>; Function_Signature(Ret (Class::*f)(Param...) const &&noexcept)->Function_Signature<Ret, Function_Params<const Class &&, Param...>, true, true>;
template<typename Func> template<typename Ret, typename Class>
Function_Signature(Func &&) -> Function_Signature< Function_Signature(Ret(Class::*f))->Function_Signature<Ret, Function_Params<Class &>, true, true, true>;
typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Return_Type,
typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Param_Types, // primary template handles types that have no nested ::type member:
decltype(Function_Signature{&std::decay_t<Func>::operator()})::is_noexcept, template<class, class = std::void_t<>>
false, struct has_call_operator : std::false_type
false, {
true };
>;
// specialization recognizes types that do have a nested ::type member:
template<class T>
struct has_call_operator<T, std::void_t<decltype(&T::operator())>> : std::true_type
{
};
template<typename Func>
auto function_signature(const Func &f)
{
if constexpr (has_call_operator<Func>::value) {
return Function_Signature<
typename decltype(Function_Signature{ &std::decay_t<Func>::operator() })::Return_Type,
typename decltype(Function_Signature{ &std::decay_t<Func>::operator() })::Param_Types,
decltype(Function_Signature{ &std::decay_t<Func>::operator() })::is_noexcept,
false,
false,
true>{};
} else {
return Function_Signature{ f };
}
} }
}// namespace chaiscript::dispatch::detail
#endif #endif

View File

@ -77,7 +77,7 @@ namespace chaiscript
std::vector<Boxed_Value> convert(Function_Params t_params, const Type_Conversions_State &t_conversions) const std::vector<Boxed_Value> convert(Function_Params t_params, const Type_Conversions_State &t_conversions) const
{ {
auto vals = t_params.to_vector(); auto vals = t_params.to_vector();
constexpr auto dynamic_object_type_info = user_type<Dynamic_Object>(); const auto dynamic_object_type_info = user_type<Dynamic_Object>();
for (size_t i = 0; i < vals.size(); ++i) for (size_t i = 0; i < vals.size(); ++i)
{ {
const auto &name = m_types[i].first; const auto &name = m_types[i].first;
@ -117,7 +117,7 @@ namespace chaiscript
// second result: needs conversions // second result: needs conversions
std::pair<bool, bool> match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept std::pair<bool, bool> match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept
{ {
constexpr auto dynamic_object_type_info = user_type<Dynamic_Object>(); const auto dynamic_object_type_info = user_type<Dynamic_Object>();
bool needs_conversion = false; bool needs_conversion = false;
if (!m_has_types) { return std::make_pair(true, needs_conversion); } if (!m_has_types) { return std::make_pair(true, needs_conversion); }
@ -252,9 +252,9 @@ namespace chaiscript
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions) noexcept static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions) noexcept
{ {
constexpr auto boxed_value_ti = user_type<Boxed_Value>(); const auto boxed_value_ti = user_type<Boxed_Value>();
constexpr auto boxed_number_ti = user_type<Boxed_Number>(); const auto boxed_number_ti = user_type<Boxed_Number>();
constexpr auto function_ti = user_type<std::shared_ptr<const Proxy_Function_Base>>(); const auto function_ti = user_type<std::shared_ptr<const Proxy_Function_Base>>();
if (ti.is_undef() if (ti.is_undef()
|| ti.bare_equal(boxed_value_ti) || ti.bare_equal(boxed_value_ti)
@ -757,7 +757,7 @@ namespace chaiscript
{ {
return false; return false;
} }
constexpr auto class_type_info = user_type<Class>(); const auto class_type_info = user_type<Class>();
return vals[0].get_type_info().bare_equal(class_type_info); return vals[0].get_type_info().bare_equal(class_type_info);
} }
@ -844,7 +844,7 @@ namespace chaiscript
namespace detail namespace detail
{ {
template<typename FuncType> template<typename FuncType>
bool types_match_except_for_arithmetic(const FuncType &t_func, const Function_Params &plist, bool types_match_except_for_arithmetic(const FuncType &t_func, const chaiscript::Function_Params &plist,
const Type_Conversions_State &t_conversions) noexcept const Type_Conversions_State &t_conversions) noexcept
{ {
const std::vector<Type_Info> &types = t_func->get_param_types(); const std::vector<Type_Info> &types = t_func->get_param_types();
@ -863,7 +863,7 @@ namespace chaiscript
} }
template<typename InItr, typename Funcs> template<typename InItr, typename Funcs>
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const Function_Params &plist, Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const chaiscript::Function_Params &plist,
const Type_Conversions_State &t_conversions, const Funcs &t_funcs) const Type_Conversions_State &t_conversions, const Funcs &t_funcs)
{ {
InItr matching_func(end); InItr matching_func(end);
@ -919,7 +919,7 @@ namespace chaiscript
); );
try { try {
return (*(matching_func->second))(Function_Params{newplist}, t_conversions); return (*(matching_func->second))(chaiscript::Function_Params{newplist}, t_conversions);
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
//parameter failed to cast //parameter failed to cast
} catch (const exception::arity_error &) { } catch (const exception::arity_error &) {

View File

@ -78,7 +78,7 @@ namespace chaiscript
*/ */
template<typename Ret, typename ... Params> template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...), bool compare_types_cast(Ret (*)(Params...),
const Function_Params &params, const Type_Conversions_State &t_conversions) noexcept const chaiscript::Function_Params &params, const Type_Conversions_State &t_conversions) noexcept
{ {
try { try {
std::vector<Boxed_Value>::size_type i = 0; std::vector<Boxed_Value>::size_type i = 0;
@ -93,7 +93,7 @@ namespace chaiscript
template<typename Callable, typename Ret, typename ... Params, size_t ... I> template<typename Callable, typename Ret, typename ... Params, size_t ... I>
Ret call_func(Ret (*)(Params...), Ret call_func(Ret (*)(Params...),
std::index_sequence<I...>, const Callable &f, std::index_sequence<I...>, const Callable &f,
[[maybe_unused]] const Function_Params &params, [[maybe_unused]] const chaiscript::Function_Params &params,
[[maybe_unused]] const Type_Conversions_State &t_conversions) [[maybe_unused]] const Type_Conversions_State &t_conversions)
{ {
return f(boxed_cast<Params>(params[I], &t_conversions)...); return f(boxed_cast<Params>(params[I], &t_conversions)...);
@ -106,7 +106,7 @@ namespace chaiscript
/// the bad_boxed_cast is passed up to the caller. /// the bad_boxed_cast is passed up to the caller.
template<typename Callable, typename Ret, typename ... Params> template<typename Callable, typename Ret, typename ... Params>
Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f, Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f,
const Function_Params &params, const Type_Conversions_State &t_conversions) const chaiscript::Function_Params &params, const Type_Conversions_State &t_conversions)
{ {
if constexpr (std::is_same_v<Ret, void>) { if constexpr (std::is_same_v<Ret, void>) {
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions); call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);

View File

@ -34,7 +34,8 @@ namespace chaiscript
// we now that the Param pack will have only one element, so we are safe expanding it here // we now that the Param pack will have only one element, so we are safe expanding it here
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<Ret, std::decay_t<Param>...>>(std::forward<Func>(func))); return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<Ret, std::decay_t<Param>...>>(std::forward<Func>(func)));
} else if constexpr (Is_Member) { } else if constexpr (Is_Member) {
auto call = [func = std::forward<Func>(func)](auto && obj, auto && ... param) noexcept(Is_Noexcept) -> decltype(auto) { // TODO some kind of bug is preventing forwarding of this noexcept for the lambda
auto call = [func = std::forward<Func>(func)](auto && obj, auto && ... param) /* noexcept(Is_Noexcept) */ -> decltype(auto) {
return (( get_first_param(Function_Params<Param...>{}, obj).*func )(std::forward<decltype(param)>(param)...)); return (( get_first_param(Function_Params<Param...>{}, obj).*func )(std::forward<decltype(param)>(param)...));
}; };
return Proxy_Function( return Proxy_Function(
@ -87,7 +88,7 @@ namespace chaiscript
template<typename T> template<typename T>
Proxy_Function fun(T &&t) Proxy_Function fun(T &&t)
{ {
return dispatch::detail::make_callable(std::forward<T>(t), dispatch::detail::Function_Signature{t}); return dispatch::detail::make_callable(std::forward<T>(t), dispatch::detail::function_signature(t));
} }

View File

@ -388,7 +388,7 @@ namespace chaiscript
template<typename T> template<typename T>
bool convertable_type() const noexcept bool convertable_type() const noexcept
{ {
constexpr auto type = user_type<T>().bare_type_info(); const auto type = user_type<T>().bare_type_info();
return thread_cache().count(type) != 0; return thread_cache().count(type) != 0;
} }
@ -645,7 +645,7 @@ namespace chaiscript
const std::map<std::string, Boxed_Value> &from_map = detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr); const std::map<std::string, Boxed_Value> &from_map = detail::Cast_Helper<const std::map<std::string, Boxed_Value> &>::cast(t_bv, nullptr);
To map; To map;
for (const std::pair<std::string, Boxed_Value> &p : from_map) { for (const std::pair<const std::string, Boxed_Value> &p : from_map) {
map.insert(std::make_pair(p.first, detail::Cast_Helper<typename To::mapped_type>::cast(p.second, nullptr))); map.insert(std::make_pair(p.first, detail::Cast_Helper<typename To::mapped_type>::cast(p.second, nullptr)));
} }

View File

@ -156,7 +156,7 @@ namespace chaiscript
m_engine.add(fun( m_engine.add(fun(
[=, this](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value { [this](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves()); Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
return t_fun(Function_Params{t_params}, s); return t_fun(Function_Params{t_params}, s);
}), "call"); }), "call");
@ -168,7 +168,7 @@ namespace chaiscript
m_engine.add(fun([this](const std::string &t_type_name){ return m_engine.get_type(t_type_name, true); }), "type"); m_engine.add(fun([this](const std::string &t_type_name){ return m_engine.get_type(t_type_name, true); }), "type");
m_engine.add(fun( m_engine.add(fun(
[=, this](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) { [this](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func)); m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
} }
), "add_type_conversion"); ), "add_type_conversion");

View File

@ -331,7 +331,6 @@ namespace chaiscript
Boxed_Value fn(this->children[0]->eval(t_ss)); Boxed_Value fn(this->children[0]->eval(t_ss));
using ConstFunctionTypePtr = const dispatch::Proxy_Function_Base *;
try { try {
return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(Function_Params{params}, t_ss.conversions()); return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(Function_Params{params}, t_ss.conversions());
} }

View File

@ -43,7 +43,7 @@ struct Stack_Vector
}; };
void pop_back() noexcept(std::is_nothrow_destructible_v<T>) { void pop_back() noexcept(std::is_nothrow_destructible_v<T>) {
(*this)[m_size--].~T(); (*this)[--m_size].~T();
} }
~Stack_Vector() noexcept(std::is_nothrow_destructible_v<T>) ~Stack_Vector() noexcept(std::is_nothrow_destructible_v<T>)

View File

@ -713,15 +713,8 @@ TEST_CASE("Object copy counts")
CHECK(Object_Copy_Count_Test::copycount() == 0); CHECK(Object_Copy_Count_Test::copycount() == 0);
CHECK(Object_Copy_Count_Test::constructcount() == 1); CHECK(Object_Copy_Count_Test::constructcount() == 1);
#ifdef CHAISCRIPT_MSVC
CHECK(Object_Copy_Count_Test::destructcount() == 3);
CHECK(Object_Copy_Count_Test::movecount() == 2);
#else
CHECK(Object_Copy_Count_Test::destructcount() == 2); CHECK(Object_Copy_Count_Test::destructcount() == 2);
CHECK(Object_Copy_Count_Test::movecount() == 1); CHECK(Object_Copy_Count_Test::movecount() == 1);
#endif
} }