- typedef void (PostUpdate) (); // Post-update function
-
- Tune() { read_results(); }
- Tune(const Tune&) = delete;
- void operator=(const Tune&) = delete;
- void read_results();
-
- static Tune& instance() { static Tune t; return t; } // Singleton
-
- // Use polymorphism to accommodate Entry of different types in the same vector
- struct EntryBase {
- virtual ~EntryBase() = default;
- virtual void init_option() = 0;
- virtual void read_option() = 0;
- };
-
- template<typename T>
- struct Entry : public EntryBase {
-
- static_assert(!std::is_const<T>::value, "Parameter cannot be const!");
-
- static_assert( std::is_same<T, int>::value
- || std::is_same<T, Value>::value
- || std::is_same<T, Score>::value
- || std::is_same<T, PostUpdate>::value, "Parameter type not supported!");
-
- Entry(const std::string& n, T& v, const SetRange& r) : name(n), value(v), range(r) {}
- void operator=(const Entry&) = delete; // Because 'value' is a reference
- void init_option() override;
- void read_option() override;
-
- std::string name;
- T& value;
- SetRange range;
- };
-
- // Our facility to fill the container, each Entry corresponds to a parameter
- // to tune. We use variadic templates to deal with an unspecified number of
- // entries, each one of a possible different type.
- static std::string next(std::string& names, bool pop = true);
-
- int add(const SetRange&, std::string&&) { return 0; }
-
- template<typename T, typename... Args>
- int add(const SetRange& range, std::string&& names, T& value, Args&&... args) {
- list.push_back(std::unique_ptr<EntryBase>(new Entry<T>(next(names), value, range)));
- return add(range, std::move(names), args...);
- }
-
- // Template specialization for arrays: recursively handle multi-dimensional arrays
- template<typename T, size_t N, typename... Args>
- int add(const SetRange& range, std::string&& names, T (&value)[N], Args&&... args) {
- for (size_t i = 0; i < N; i++)
- add(range, next(names, i == N - 1) + "[" + std::to_string(i) + "]", value[i]);
- return add(range, std::move(names), args...);
- }
-
- // Template specialization for SetRange
- template<typename... Args>
- int add(const SetRange&, std::string&& names, SetRange& value, Args&&... args) {
- return add(value, (next(names), std::move(names)), args...);
- }
-
- std::vector<std::unique_ptr<EntryBase>> list;
-
-public:
- template<typename... Args>
- static int add(const std::string& names, Args&&... args) {
- return instance().add(SetDefaultRange, names.substr(1, names.size() - 2), args...); // Remove trailing parenthesis
- }
- static void init() { for (auto& e : instance().list) e->init_option(); read_options(); } // Deferred, due to UCI::Options access
- static void read_options() { for (auto& e : instance().list) e->read_option(); }
- static bool update_on_last;
+ using PostUpdate = void(); // Post-update function
+
+ Tune() { read_results(); }
+ Tune(const Tune&) = delete;
+ void operator=(const Tune&) = delete;
+ void read_results();
+
+ static Tune& instance() {
+ static Tune t;
+ return t;
+ } // Singleton
+
+ // Use polymorphism to accommodate Entry of different types in the same vector
+ struct EntryBase {
+ virtual ~EntryBase() = default;
+ virtual void init_option() = 0;
+ virtual void read_option() = 0;
+ };
+
+ template<typename T>
+ struct Entry: public EntryBase {
+
+ static_assert(!std::is_const_v<T>, "Parameter cannot be const!");
+
+ static_assert(std::is_same_v<T, int> || std::is_same_v<T, Value>
+ || std::is_same_v<T, PostUpdate>,
+ "Parameter type not supported!");
+
+ Entry(const std::string& n, T& v, const SetRange& r) :
+ name(n),
+ value(v),
+ range(r) {}
+ void operator=(const Entry&) = delete; // Because 'value' is a reference
+ void init_option() override;
+ void read_option() override;
+
+ std::string name;
+ T& value;
+ SetRange range;
+ };
+
+ // Our facility to fill the container, each Entry corresponds to a parameter
+ // to tune. We use variadic templates to deal with an unspecified number of
+ // entries, each one of a possible different type.
+ static std::string next(std::string& names, bool pop = true);
+
+ int add(const SetRange&, std::string&&) { return 0; }
+
+ template<typename T, typename... Args>
+ int add(const SetRange& range, std::string&& names, T& value, Args&&... args) {
+ list.push_back(std::unique_ptr<EntryBase>(new Entry<T>(next(names), value, range)));
+ return add(range, std::move(names), args...);
+ }
+
+ // Template specialization for arrays: recursively handle multi-dimensional arrays
+ template<typename T, size_t N, typename... Args>
+ int add(const SetRange& range, std::string&& names, T (&value)[N], Args&&... args) {
+ for (size_t i = 0; i < N; i++)
+ add(range, next(names, i == N - 1) + "[" + std::to_string(i) + "]", value[i]);
+ return add(range, std::move(names), args...);
+ }
+
+ // Template specialization for SetRange
+ template<typename... Args>
+ int add(const SetRange&, std::string&& names, SetRange& value, Args&&... args) {
+ return add(value, (next(names), std::move(names)), args...);
+ }
+
+ std::vector<std::unique_ptr<EntryBase>> list;
+
+ public:
+ template<typename... Args>
+ static int add(const std::string& names, Args&&... args) {
+ return instance().add(SetDefaultRange, names.substr(1, names.size() - 2),
+ args...); // Remove trailing parenthesis
+ }
+ static void init() {
+ for (auto& e : instance().list)
+ e->init_option();
+ read_options();
+ } // Deferred, due to UCI::Options access
+ static void read_options() {
+ for (auto& e : instance().list)
+ e->read_option();
+ }
+ static bool update_on_last;