mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-09-10 03:52:55 +02:00
Allow FluidSynth and OpenAL Soft to compile with -fno-exceptions -fno-rtti
in libretro builds
This commit is contained in:
parent
94e0f99643
commit
082bd25be5
9 changed files with 4217 additions and 165 deletions
|
@ -34,6 +34,10 @@ global_cpp_args = []
|
|||
global_link_args = []
|
||||
libretro_ruby_args = []
|
||||
|
||||
if is_libretro
|
||||
global_cpp_args += '-fno-rtti'
|
||||
endif
|
||||
|
||||
sizeof = {'void*': compilers['cpp'].sizeof('void*'),
|
||||
'long': compilers['cpp'].sizeof('long')
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if !defined(MKXPZ_NO_PTHREAD_H_MUTEX) || !defined(MKXPZ_NO_PTHREAD_H_THREAD)
|
||||
|
@ -37,6 +38,18 @@
|
|||
# include <semaphore.h>
|
||||
#endif
|
||||
|
||||
#if !defined(__cplusplus) || defined(MKXPZ_NO_EXCEPTIONS)
|
||||
# define MKXPZ_THROW(...) do { fprintf(stderr, "Exception thrown: %s\n", (__VA_ARGS__).what()); fflush(stderr); abort(); } while (0)
|
||||
# define MKXPZ_RETHROW do { } while (0)
|
||||
# define MKXPZ_TRY if (1)
|
||||
# define MKXPZ_CATCH(...) if (0)
|
||||
#else
|
||||
# define MKXPZ_THROW(...) throw __VA_ARGS__
|
||||
# define MKXPZ_RETHROW throw
|
||||
# define MKXPZ_TRY try
|
||||
# define MKXPZ_CATCH(...) catch (__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifndef MKXPZ_NO_STD_MUTEX
|
||||
typedef struct {
|
||||
void *inner;
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
url = https://github.com/mkxp-z/fluidsynth-sans-glib
|
||||
revision = 5c7716bda52f4f86271f32337c79f806f9402144
|
||||
depth = 1
|
||||
diff_files = fluidsynth-cmake-policy.patch, fluidsynth-emscripten-endian.patch, fluidsynth-executable.patch, fluidsynth-linker-flags.patch, fluidsynth-mkxp-polyfill.patch, fluidsynth-pic.patch, fluidsynth-pthreads.patch, fluidsynth-test-doc.patch
|
||||
diff_files = fluidsynth-cmake-policy.patch, fluidsynth-emscripten-endian.patch, fluidsynth-executable.patch, fluidsynth-linker-flags.patch, fluidsynth-mkxp-polyfill.patch, fluidsynth-no-exceptions.patch, fluidsynth-pic.patch, fluidsynth-pthreads.patch, fluidsynth-test-doc.patch
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
url = https://github.com/kcat/openal-soft
|
||||
revision = 1.24.2
|
||||
depth = 1
|
||||
diff_files = openal-soft-android-log.patch, openal-soft-atomic.patch, openal-soft-buildtype.patch, openal-soft-c11.patch, openal-soft-constexpr.patch, openal-soft-emscripten-pthread.patch, openal-soft-emscripten-setschedparam.patch, openal-soft-emscripten-symbol-conflict.patch, openal-soft-event-thread.patch, openal-soft-filesystem.patch, openal-soft-flockfile.patch, openal-soft-int32.patch, openal-soft-mkxp-polyfill.patch, openal-soft-null.patch, openal-soft-pic.patch, openal-soft-ps3.patch
|
||||
diff_files = openal-soft-0001-no-exceptions.patch, openal-soft-android-log.patch, openal-soft-atomic.patch, openal-soft-buildtype.patch, openal-soft-c11.patch, openal-soft-constexpr.patch, openal-soft-emscripten-pthread.patch, openal-soft-emscripten-setschedparam.patch, openal-soft-emscripten-symbol-conflict.patch, openal-soft-event-thread.patch, openal-soft-filesystem.patch, openal-soft-flockfile.patch, openal-soft-int32.patch, openal-soft-mkxp-polyfill.patch, openal-soft-null.patch, openal-soft-pic.patch, openal-soft-ps3.patch
|
||||
|
|
106
subprojects/packagefiles/fluidsynth-no-exceptions.patch
Normal file
106
subprojects/packagefiles/fluidsynth-no-exceptions.patch
Normal file
|
@ -0,0 +1,106 @@
|
|||
# Allows FluidSynth to compile with C++ exceptions disabled.
|
||||
|
||||
--- a/src/midi/fluid_seq_queue.cpp
|
||||
+++ b/src/midi/fluid_seq_queue.cpp
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <deque>
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
-
|
||||
+#include "../../../src/mkxp-polyfill.h"
|
||||
/*
|
||||
* This is an implementation of an event queue, sorted according to their timestamp.
|
||||
*
|
||||
@@ -119,7 +119,7 @@ int event_compare_for_test(const fluid_event_t* left, const fluid_event_t* right
|
||||
|
||||
void* new_fluid_seq_queue(int nb_events)
|
||||
{
|
||||
- try
|
||||
+ MKXPZ_TRY
|
||||
{
|
||||
// As workaround for a missing deque::reserve(), allocate a deque with a size of nb_events
|
||||
seq_queue_t* queue = new seq_queue_t(nb_events);
|
||||
@@ -130,7 +130,7 @@ void* new_fluid_seq_queue(int nb_events)
|
||||
|
||||
return queue;
|
||||
}
|
||||
- catch(...)
|
||||
+ MKXPZ_CATCH(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ void delete_fluid_seq_queue(void *que)
|
||||
|
||||
int fluid_seq_queue_push(void *que, const fluid_event_t *evt)
|
||||
{
|
||||
- try
|
||||
+ MKXPZ_TRY
|
||||
{
|
||||
seq_queue_t& queue = *static_cast<seq_queue_t*>(que);
|
||||
|
||||
@@ -152,7 +152,7 @@ int fluid_seq_queue_push(void *que, const fluid_event_t *evt)
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
- catch(...)
|
||||
+ MKXPZ_CATCH(...)
|
||||
{
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
--- a/src/midi/fluid_seqbind_notes.cpp
|
||||
+++ b/src/midi/fluid_seqbind_notes.cpp
|
||||
@@ -21,7 +21,7 @@
|
||||
#include "fluid_seqbind_notes.h"
|
||||
|
||||
#include <set>
|
||||
-
|
||||
+#include "../../../src/mkxp-polyfill.h"
|
||||
/*
|
||||
* This is a hash container allows us to detect overlapping notes, by storing a bunch of unique integers,
|
||||
* that allow us to track noteOn events.
|
||||
@@ -63,12 +63,12 @@ fluid_note_id_t fluid_note_compute_id(int chan, short key)
|
||||
|
||||
void* new_fluid_note_container()
|
||||
{
|
||||
- try
|
||||
+ MKXPZ_TRY
|
||||
{
|
||||
note_container_t* cont = new note_container_t;
|
||||
return cont;
|
||||
}
|
||||
- catch(...)
|
||||
+ MKXPZ_CATCH(...)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -83,14 +83,14 @@ void delete_fluid_note_container(void *cont)
|
||||
// FLUID_FAILED in case of error.
|
||||
int fluid_note_container_insert(void* cont, fluid_note_id_t id)
|
||||
{
|
||||
- try
|
||||
+ MKXPZ_TRY
|
||||
{
|
||||
std::pair<note_container_t::iterator, bool> res = static_cast<note_container_t*>(cont)->insert(id);
|
||||
// res.second tells us whether the element was inserted
|
||||
// by inverting it, we know whether it contained the element previously
|
||||
return !res.second;
|
||||
}
|
||||
- catch(...)
|
||||
+ MKXPZ_CATCH(...)
|
||||
{
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
@@ -98,11 +98,11 @@ int fluid_note_container_insert(void* cont, fluid_note_id_t id)
|
||||
|
||||
void fluid_note_container_remove(void* cont, fluid_note_id_t id)
|
||||
{
|
||||
- try
|
||||
+ MKXPZ_TRY
|
||||
{
|
||||
static_cast<note_container_t*>(cont)->erase(id);
|
||||
}
|
||||
- catch(...)
|
||||
+ MKXPZ_CATCH(...)
|
||||
{
|
||||
// should never happen
|
||||
}
|
4066
subprojects/packagefiles/openal-soft-0001-no-exceptions.patch
Normal file
4066
subprojects/packagefiles/openal-soft-0001-no-exceptions.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
|||
# Removes all exception throwing and logging inside of functions marked `constexpr` since old versions of GCC don't support it.
|
||||
# Fixes problems in the code that cause compilation errors due to stricter handling of constexpr in old versions of GCC.
|
||||
# When building for PlayStation 3, we use an old enough version of GCC for this to be a problem.
|
||||
|
||||
--- a/al/auxeffectslot.cpp
|
||||
|
@ -12,135 +12,6 @@
|
|||
return EffectSlotType::None;
|
||||
}
|
||||
|
||||
--- a/al/buffer.cpp
|
||||
+++ b/al/buffer.cpp
|
||||
@@ -88,8 +88,8 @@ constexpr auto EnumFromAmbiLayout(AmbiLayout layout) -> ALenum
|
||||
case AmbiLayout::FuMa: return AL_FUMA_SOFT;
|
||||
case AmbiLayout::ACN: return AL_ACN_SOFT;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Invalid AmbiLayout: {}",
|
||||
- int{al::to_underlying(layout)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
constexpr auto AmbiScalingFromEnum(ALenum scale) noexcept -> std::optional<AmbiScaling>
|
||||
@@ -111,8 +111,8 @@ constexpr auto EnumFromAmbiScaling(AmbiScaling scale) -> ALenum
|
||||
case AmbiScaling::N3D: return AL_N3D_SOFT;
|
||||
case AmbiScaling::UHJ: break;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Invalid AmbiScaling: {}",
|
||||
- int{al::to_underlying(scale)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
#if ALSOFT_EAX
|
||||
--- a/al/debug.cpp
|
||||
+++ b/al/debug.cpp
|
||||
@@ -110,8 +110,8 @@ constexpr auto GetDebugSourceEnum(DebugSource source) -> ALenum
|
||||
case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_EXT;
|
||||
case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_EXT;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Unexpected debug source value: {}",
|
||||
- int{al::to_underlying(source)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
constexpr auto GetDebugTypeEnum(DebugType type) -> ALenum
|
||||
@@ -128,8 +128,8 @@ constexpr auto GetDebugTypeEnum(DebugType type) -> ALenum
|
||||
case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_EXT;
|
||||
case DebugType::Other: return AL_DEBUG_TYPE_OTHER_EXT;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Unexpected debug type value: {}",
|
||||
- int{al::to_underlying(type)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
constexpr auto GetDebugSeverityEnum(DebugSeverity severity) -> ALenum
|
||||
@@ -141,8 +141,8 @@ constexpr auto GetDebugSeverityEnum(DebugSeverity severity) -> ALenum
|
||||
case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_EXT;
|
||||
case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_EXT;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Unexpected debug severity value: {}",
|
||||
- int{al::to_underlying(severity)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
|
||||
--- a/al/effects/chorus.cpp
|
||||
+++ b/al/effects/chorus.cpp
|
||||
@@ -43,8 +43,8 @@ constexpr ALenum EnumFromWaveform(ChorusWaveform type)
|
||||
case ChorusWaveform::Sinusoid: return AL_CHORUS_WAVEFORM_SINUSOID;
|
||||
case ChorusWaveform::Triangle: return AL_CHORUS_WAVEFORM_TRIANGLE;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Invalid chorus waveform: {}",
|
||||
- int{al::to_underlying(type)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
constexpr EffectProps genDefaultChorusProps() noexcept
|
||||
--- a/al/effects/fshifter.cpp
|
||||
+++ b/al/effects/fshifter.cpp
|
||||
@@ -40,7 +40,7 @@ constexpr ALenum EnumFromDirection(FShifterDirection dir)
|
||||
case FShifterDirection::Up: return AL_FREQUENCY_SHIFTER_DIRECTION_UP;
|
||||
case FShifterDirection::Off: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Invalid direction: {}", int{al::to_underlying(dir)})};
|
||||
+ abort();
|
||||
}
|
||||
|
||||
constexpr EffectProps genDefaultProps() noexcept
|
||||
--- a/al/effects/modulator.cpp
|
||||
+++ b/al/effects/modulator.cpp
|
||||
@@ -40,8 +40,8 @@ constexpr ALenum EnumFromWaveform(ModulatorWaveform type)
|
||||
case ModulatorWaveform::Sawtooth: return AL_RING_MODULATOR_SAWTOOTH;
|
||||
case ModulatorWaveform::Square: return AL_RING_MODULATOR_SQUARE;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Invalid modulator waveform: {}",
|
||||
- int{al::to_underlying(type)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
constexpr EffectProps genDefaultProps() noexcept
|
||||
--- a/al/effects/vmorpher.cpp
|
||||
+++ b/al/effects/vmorpher.cpp
|
||||
@@ -97,7 +97,7 @@ constexpr ALenum EnumFromPhenome(VMorpherPhenome phenome)
|
||||
HANDLE_PHENOME(V);
|
||||
HANDLE_PHENOME(Z);
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Invalid phenome: {}", int{al::to_underlying(phenome)})};
|
||||
+ abort();
|
||||
#undef HANDLE_PHENOME
|
||||
}
|
||||
|
||||
@@ -119,8 +119,8 @@ constexpr ALenum EnumFromWaveform(VMorpherWaveform type)
|
||||
case VMorpherWaveform::Triangle: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE;
|
||||
case VMorpherWaveform::Sawtooth: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH;
|
||||
}
|
||||
- throw std::runtime_error{fmt::format("Invalid vocal morpher waveform: {}",
|
||||
- int{al::to_underlying(type)})};
|
||||
+
|
||||
+ abort();
|
||||
}
|
||||
|
||||
constexpr EffectProps genDefaultProps() noexcept
|
||||
--- a/al/state.cpp
|
||||
+++ b/al/state.cpp
|
||||
@@ -141,7 +141,7 @@ constexpr auto ALenumFromDistanceModel(DistanceModel model) -> ALenum
|
||||
case DistanceModel::Exponent: return AL_EXPONENT_DISTANCE;
|
||||
case DistanceModel::ExponentClamped: return AL_EXPONENT_DISTANCE_CLAMPED;
|
||||
}
|
||||
- throw std::runtime_error{"Unexpected distance model "+std::to_string(static_cast<int>(model))};
|
||||
+ abort();
|
||||
}
|
||||
|
||||
enum PropertyValue : ALenum {
|
||||
--- a/common/alstring.h
|
||||
+++ b/common/alstring.h
|
||||
@@ -22,15 +22,15 @@ auto sizei(const std::basic_string<Ts...> &str) noexcept -> int
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
|
||||
void StartEventThrd(ALCcontext *ctx)
|
||||
{
|
||||
- try {
|
||||
- MKXPZ_TRY {
|
||||
- ctx->mEventThread = std::thread{EventThread, ctx};
|
||||
- }
|
||||
- catch(std::exception& e) {
|
||||
- ERR("Failed to start event thread: {}", e.what());
|
||||
- MKXPZ_CATCH(std::exception& e) {
|
||||
|
||||
- }
|
||||
- catch(...) {
|
||||
- MKXPZ_CATCH(...) {
|
||||
- ERR("Failed to start event thread! Expect problems.");
|
||||
- }
|
||||
+
|
||||
|
@ -22,7 +22,6 @@
|
|||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
+
|
||||
}
|
||||
|
||||
|
|
|
@ -249,45 +249,37 @@
|
|||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
--- a/common/alassert.cpp
|
||||
+++ b/common/alassert.cpp
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "alassert.h"
|
||||
|
||||
#include <stdexcept>
|
||||
-#include <string>
|
||||
+#include "../../src/mkxp-polyfill.h"
|
||||
|
||||
namespace {
|
||||
|
||||
--- a/common/alsem.cpp
|
||||
+++ b/common/alsem.cpp
|
||||
@@ -55,8 +55,6 @@ void semaphore::post()
|
||||
@@ -55,8 +55,8 @@ void semaphore::post()
|
||||
void semaphore::wait() noexcept
|
||||
{ WaitForSingleObject(static_cast<HANDLE>(mSem), INFINITE); }
|
||||
|
||||
-bool semaphore::try_wait() noexcept
|
||||
-{ return WaitForSingleObject(static_cast<HANDLE>(mSem), 0) == WAIT_OBJECT_0; }
|
||||
+
|
||||
+
|
||||
|
||||
} // namespace al
|
||||
|
||||
@@ -83,8 +81,6 @@ void semaphore::post()
|
||||
@@ -83,8 +83,8 @@ void semaphore::post()
|
||||
void semaphore::wait() noexcept
|
||||
{ dispatch_semaphore_wait(mSem, DISPATCH_TIME_FOREVER); }
|
||||
|
||||
-bool semaphore::try_wait() noexcept
|
||||
-{ return dispatch_semaphore_wait(mSem, DISPATCH_TIME_NOW) == 0; }
|
||||
+
|
||||
+
|
||||
|
||||
} // namespace al
|
||||
|
||||
@@ -96,27 +92,25 @@ namespace al {
|
||||
@@ -96,27 +96,27 @@ namespace al {
|
||||
|
||||
semaphore::semaphore(unsigned int initial)
|
||||
{
|
||||
- if(sem_init(&mSem, 0, initial) != 0)
|
||||
- throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again));
|
||||
+ if(mkxp_sem_init(&mSem, initial) != 0)
|
||||
+ abort();
|
||||
MKXPZ_THROW(std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)));
|
||||
}
|
||||
|
||||
semaphore::~semaphore()
|
||||
|
@ -297,20 +289,21 @@
|
|||
void semaphore::post()
|
||||
{
|
||||
- if(sem_post(&mSem) != 0)
|
||||
- throw std::system_error(std::make_error_code(std::errc::value_too_large));
|
||||
+ if(mkxp_sem_post(&mSem) != 0)
|
||||
+ abort();
|
||||
MKXPZ_THROW(std::system_error(std::make_error_code(std::errc::value_too_large)));
|
||||
}
|
||||
|
||||
void semaphore::wait() noexcept
|
||||
{
|
||||
- while(sem_wait(&mSem) == -1 && errno == EINTR) {
|
||||
+ while(mkxp_sem_wait(&mSem) == -1 && errno == EINTR) {
|
||||
+ while(mkxp_sem_wait(&mSem) == -1) {
|
||||
}
|
||||
}
|
||||
|
||||
-bool semaphore::try_wait() noexcept
|
||||
-{ return sem_trywait(&mSem) == 0; }
|
||||
+
|
||||
+
|
||||
|
||||
} // namespace al
|
||||
|
||||
|
@ -321,7 +314,7 @@
|
|||
#endif
|
||||
#elif !defined(_WIN32)
|
||||
-#include <semaphore.h>
|
||||
+#include "../../src/mkxp-polyfill.h"
|
||||
+
|
||||
#endif
|
||||
|
||||
namespace al {
|
||||
|
@ -334,11 +327,12 @@
|
|||
#endif
|
||||
native_type mSem{};
|
||||
|
||||
@@ -35,7 +35,6 @@ public:
|
||||
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
void post();
|
||||
void wait() noexcept;
|
||||
- bool try_wait() noexcept;
|
||||
+
|
||||
};
|
||||
|
||||
} // namespace al
|
||||
|
@ -405,7 +399,7 @@
|
|||
@@ -5,7 +5,7 @@
|
||||
#include <stdexcept>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../../src/mkxp-polyfill.h"
|
||||
-#ifdef _WIN32
|
||||
+#if false
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
|
@ -443,16 +437,15 @@
|
|||
tss()
|
||||
{
|
||||
- if(int res{tss_create(&mTss, nullptr)}; res != thrd_success)
|
||||
+ if ((mTss = static_cast<void **>(std::malloc(sizeof *mTss))) == nullptr)
|
||||
throw std::runtime_error{"al::tss::tss()"};
|
||||
+ if((mTss = static_cast<void **>(std::malloc(sizeof *mTss))) == nullptr)
|
||||
MKXPZ_THROW(std::runtime_error{"al::tss::tss()"});
|
||||
+ *mTss = nullptr;
|
||||
}
|
||||
explicit tss(const T &init) : tss{}
|
||||
{
|
||||
- if(int res{tss_set(mTss, to_ptr(init))}; res != thrd_success)
|
||||
- throw std::runtime_error{"al::tss::tss(T)"};
|
||||
+ if ((mTss = static_cast<void **>(std::malloc(sizeof *mTss))) == nullptr)
|
||||
+ throw std::runtime_error{"al::tss::tss()"};
|
||||
+ if((mTss = static_cast<void **>(std::malloc(sizeof *mTss))) == nullptr)
|
||||
MKXPZ_THROW(std::runtime_error{"al::tss::tss(T)"});
|
||||
+ *mTss = to_ptr(init);
|
||||
}
|
||||
- ~tss() { tss_delete(mTss); }
|
||||
|
@ -461,7 +454,7 @@
|
|||
void set(const T &value) const
|
||||
{
|
||||
- if(int res{tss_set(mTss, to_ptr(value))}; res != thrd_success)
|
||||
- throw std::runtime_error{"al::tss::set(T)"};
|
||||
- MKXPZ_THROW(std::runtime_error{"al::tss::set(T)"});
|
||||
+ *mTss = to_ptr(value);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue