mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-11 11:17:38 +08:00
ChaiScript 6 always used a shared_ptr to wrap C++ objects created in ChaiScript. Newer versions avoid this by only wrapping objects that cannot be copied. This has the side effect that ChaiScript depends on correctly implemented C++ copy and move constructors in unexpected locations. I don't think the reduced overhead (by avoiding the shared_ptr) justifies the new behavior in every case. Therefore, I suggest we temporarily only perform this optimization if the class is trivially destructible, until unexpected copies and moves in ChaiScript are fixed (if this is even possible), or there is a sanitizer/compiler warning that can detect these cases. Before the change the following code will call the ctor once, move once, and the dtor twice: auto obj = MoveableObject(); After this change it will only call the ctor once and the dtor once.
57 lines
2.5 KiB
C++
57 lines
2.5 KiB
C++
// This file is distributed under the BSD License.
|
|
// See "license.txt" for details.
|
|
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
|
// Copyright 2009-2018, Jason Turner (jason@emptycrate.com)
|
|
// http://www.chaiscript.com
|
|
|
|
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
|
|
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
|
|
|
#ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
|
#define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_
|
|
|
|
#include "proxy_functions.hpp"
|
|
|
|
namespace chaiscript::dispatch::detail {
|
|
template<typename Class, typename... Params>
|
|
Proxy_Function build_constructor_(Class (*)(Params...)) {
|
|
// is_copy_constructible is required to avoid compilation errors if classes cannot be copied
|
|
// is_trivially_destructible is required to avoid bugs if classes don't correctly implement
|
|
// copy or move. To avoid unexpected runtime behavior we allocate them as shared_ptrs.
|
|
if constexpr (!std::is_copy_constructible_v<Class> || !std::is_trivially_destructible_v<Class>) {
|
|
auto call = [](auto &&...param) { return std::make_shared<Class>(std::forward<decltype(param)>(param)...); };
|
|
|
|
return Proxy_Function(
|
|
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
|
dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class>(Params...), decltype(call)>>(call));
|
|
} else if constexpr (true) {
|
|
auto call = [](auto &&...param) { return Class{std::forward<decltype(param)>(param)...}; };
|
|
|
|
return Proxy_Function(
|
|
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Class(Params...), decltype(call)>>(
|
|
call));
|
|
}
|
|
}
|
|
} // namespace chaiscript::dispatch::detail
|
|
|
|
namespace chaiscript {
|
|
/// \brief Generates a constructor function for use with ChaiScript
|
|
///
|
|
/// \tparam T The signature of the constructor to generate. In the form of: ClassType (ParamType1, ParamType2, ...)
|
|
///
|
|
/// Example:
|
|
/// \code
|
|
/// chaiscript::ChaiScript chai;
|
|
/// // Create a new function that creates a MyClass object using the (int, float) constructor
|
|
/// // and call that function "MyClass" so that it appears as a normal constructor to the user.
|
|
/// chai.add(constructor<MyClass (int, float)>(), "MyClass");
|
|
/// \endcode
|
|
template<typename T>
|
|
Proxy_Function constructor() {
|
|
T *f = nullptr;
|
|
return (dispatch::detail::build_constructor_(f));
|
|
}
|
|
} // namespace chaiscript
|
|
|
|
#endif
|