Apply re-formatting to C++ in src/ tree.
[alexxy/gromacs.git] / src / gromacs / options / basicoptions.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2010-2018, The GROMACS development team.
5  * Copyright (c) 2019,2020, by the GROMACS development team, led by
6  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7  * and including many others, as listed in the AUTHORS file in the
8  * top-level source directory and at http://www.gromacs.org.
9  *
10  * GROMACS is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1
13  * of the License, or (at your option) any later version.
14  *
15  * GROMACS is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with GROMACS; if not, see
22  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
24  *
25  * If you want to redistribute modifications to GROMACS, please
26  * consider that scientific software is very special. Version
27  * control is crucial - bugs must be traceable. We will be happy to
28  * consider code for inclusion in the official distribution, but
29  * derived work must not be called official GROMACS. Details are found
30  * in the README & COPYING files - if they are missing, get the
31  * official version at http://www.gromacs.org.
32  *
33  * To help us fund GROMACS development, we humbly ask that you cite
34  * the research papers on the package. Check out http://www.gromacs.org.
35  */
36 /*! \file
37  * \brief
38  * Declares option objects for basic option types.
39  *
40  * Together with options.h, this header forms the part of the public API
41  * that most classes will use to provide options.
42  *
43  * \author Teemu Murtola <teemu.murtola@gmail.com>
44  * \inpublicapi
45  * \ingroup module_options
46  */
47 #ifndef GMX_OPTIONS_BASICOPTIONS_H
48 #define GMX_OPTIONS_BASICOPTIONS_H
49
50 #include <memory>
51 #include <string>
52 #include <vector>
53
54 #include "gromacs/options/abstractoption.h"
55 #include "gromacs/utility/arrayref.h"
56 #include "gromacs/utility/basedefinitions.h"
57 #include "gromacs/utility/enumerationhelpers.h"
58 #include "gromacs/utility/gmxassert.h"
59
60 #include "ivaluestore.h"
61
62 namespace gmx
63 {
64
65 class BooleanOptionInfo;
66 class BooleanOptionStorage;
67 class IntegerOptionInfo;
68 class IntegerOptionStorage;
69 class Int64OptionInfo;
70 class Int64OptionStorage;
71 class DoubleOptionInfo;
72 class DoubleOptionStorage;
73 class FloatOptionInfo;
74 class FloatOptionStorage;
75 class StringOptionInfo;
76 class StringOptionStorage;
77 class EnumOptionInfo;
78 class EnumOptionStorage;
79
80 //! \addtogroup module_options
81 //! \{
82
83 /*! \brief
84  * Specifies an option that provides boolean values.
85  *
86  * Example:
87  * \code
88    bool  bPBC;
89    using gmx::BooleanOption;
90    options.addOption(BooleanOption("pbc").store(&bPBC));
91  * \endcode
92  *
93  * Public methods in this class do not throw.
94  *
95  * \inpublicapi
96  */
97 class BooleanOption : public OptionTemplate<bool, BooleanOption>
98 {
99 public:
100     //! OptionInfo subclass corresponding to this option type.
101     typedef BooleanOptionInfo InfoType;
102
103     //! Initializes an option with the given name.
104     explicit BooleanOption(const char* name) : MyBase(name) {}
105
106 private:
107     //! Creates a BooleanOptionStorage object.
108     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
109 };
110
111 /*! \brief
112  * Specifies an option that provides integer values.
113  *
114  * Examples:
115  * \code
116    using gmx::IntegerOption;
117    // Simple option
118    int  rcut = 0;
119    options.addOption(IntegerOption("rcut").store(&rcut));
120    // Vector-valued option
121    int  box[3] = {1, 1, 1};  // Default value
122    options.addOption(IntegerOption("box").store(box).vector());
123  * \endcode
124  *
125  * Public methods in this class do not throw.
126  *
127  * \inpublicapi
128  */
129 class IntegerOption : public OptionTemplate<int, IntegerOption>
130 {
131 public:
132     //! OptionInfo subclass corresponding to this option type.
133     typedef IntegerOptionInfo InfoType;
134
135     //! Initializes an option with the given name.
136     explicit IntegerOption(const char* name) : MyBase(name) {}
137
138     /*! \brief
139      * Sets the option to return a vector value.
140      *
141      * A vector value returns a fixed number of values, the default being
142      * three (can be changed with valueCount()).  However, it also accepts
143      * a single value, in which case the value is used to fill the whole
144      * vector.
145      */
146     MyClass& vector()
147     {
148         setVector();
149         return me();
150     }
151
152 private:
153     //! Creates an IntegerOptionStorage object.
154     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
155
156     /*! \brief
157      * Needed to initialize IntegerOptionStorage from this class without
158      * otherwise unnecessary accessors.
159      */
160     friend class IntegerOptionStorage;
161 };
162
163 /*! \brief
164  * Specifies an option that provides 64-bit integer values.
165  *
166  * Public methods in this class do not throw.
167  *
168  * \see IntegerOption
169  *
170  * \inpublicapi
171  */
172 class Int64Option : public OptionTemplate<int64_t, Int64Option>
173 {
174 public:
175     //! OptionInfo subclass corresponding to this option type.
176     typedef Int64OptionInfo InfoType;
177
178     //! Initializes an option with the given name.
179     explicit Int64Option(const char* name) : MyBase(name) {}
180
181 private:
182     //! Creates an Int64OptionStorage object.
183     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
184
185     /*! \brief
186      * Needed to initialize Int64OptionStorage from this class without
187      * otherwise unnecessary accessors.
188      */
189     friend class Int64OptionStorage;
190 };
191
192 /*! \brief
193  * Specifies an option that provides floating-point (double) values.
194  *
195  * Public methods in this class do not throw.
196  *
197  * \inpublicapi
198  */
199 class DoubleOption : public OptionTemplate<double, DoubleOption>
200 {
201 public:
202     //! OptionInfo subclass corresponding to this option type.
203     typedef DoubleOptionInfo InfoType;
204
205     //! Initializes an option with the given name.
206     explicit DoubleOption(const char* name) : MyBase(name), bTime_(false) {}
207
208     //! \copydoc IntegerOption::vector()
209     MyClass& vector()
210     {
211         setVector();
212         return me();
213     }
214     /*! \brief
215      * Marks this option as providing a time value whose unit can be changed.
216      *
217      * By itself, this option does nothing.  It marks the option as a time
218      * value such that TimeUnitManager::scaleTimeOptions() can process it.
219      * In typical cases, \Gromacs scales the time options just before
220      * Options::finish() has been called, so the option value is only
221      * available after all option values have been processed.
222      * All values in the program are in ps (including any default value);
223      * user-provided values are scaled according to the time unit set in
224      * TimeUnitManager.
225      */
226     MyClass& timeValue()
227     {
228         bTime_ = true;
229         return me();
230     }
231
232 private:
233     //! Creates a DoubleOptionStorage object.
234     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
235
236     bool bTime_;
237
238     /*! \brief
239      * Needed to initialize DoubleOptionStorage from this class without
240      * otherwise unnecessary accessors.
241      */
242     friend class DoubleOptionStorage;
243 };
244
245 /*! \brief
246  * Specifies an option that provides floating-point (float) values.
247  *
248  * Public methods in this class do not throw.
249  *
250  * \see DoubleOption
251  *
252  * \inpublicapi
253  */
254 class FloatOption : public OptionTemplate<float, FloatOption>
255 {
256 public:
257     //! OptionInfo subclass corresponding to this option type.
258     typedef FloatOptionInfo InfoType;
259
260     //! Initializes an option with the given name.
261     explicit FloatOption(const char* name) : MyBase(name), bTime_(false) {}
262
263     //! \copydoc IntegerOption::vector()
264     MyClass& vector()
265     {
266         setVector();
267         return me();
268     }
269     //! \copydoc DoubleOption::timeValue()
270     MyClass& timeValue()
271     {
272         bTime_ = true;
273         return me();
274     }
275
276 private:
277     //! Creates a FloatOptionStorage object.
278     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
279
280     bool bTime_;
281
282     /*! \brief
283      * Needed to initialize FloatOptionStorage from this class without
284      * otherwise unnecessary accessors.
285      */
286     friend class FloatOptionStorage;
287 };
288
289 /*! \brief
290  * Specifies an option that provides string values.
291  *
292  * Examples:
293  * \code
294    using gmx::StringOption;
295    // Simple option
296    std::string  str;
297    options.addOption(StringOption("str").store(&str));
298    // Option that only accepts predefined values
299    const char * const  allowed[] = { "atom", "residue", "molecule" };
300    std::string  str;
301    options.addOption(StringOption("type").enumValue(allowed).store(&str));
302  * \endcode
303  *
304  * Public methods in this class do not throw.
305  *
306  * \inpublicapi
307  */
308 class StringOption : public OptionTemplate<std::string, StringOption>
309 {
310 public:
311     //! OptionInfo subclass corresponding to this option type.
312     typedef StringOptionInfo InfoType;
313
314     //! Initializes an option with the given name.
315     explicit StringOption(const char* name) :
316         MyBase(name),
317         enumValues_(nullptr),
318         enumValuesCount_(0),
319         defaultEnumIndex_(-1)
320     {
321     }
322
323     /*! \brief
324      * Sets the option to only accept one of a fixed set of strings.
325      *
326      * \param[in] values  Array of strings to accept.
327      *
328      * Also accepts prefixes of the strings; if a prefix matches more than
329      * one of the possible strings, the shortest one is used (in a tie, the
330      * first one is).
331      *
332      * The strings are copied once the option is created.
333      */
334     template<size_t count>
335     MyClass& enumValue(const char* const (&values)[count])
336     {
337         GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
338         enumValues_      = values;
339         enumValuesCount_ = count;
340         return me();
341     }
342     /*! \brief
343      * Sets the option to only accept one of a fixed set of strings.
344      *
345      * \param[in] values  Array of strings to accept, with a NULL pointer
346      *      following the last string.
347      *
348      * Works otherwise as the array version, but accepts a pointer to
349      * an array of undetermined length.  The end of the array is indicated
350      * by a NULL pointer in the array.
351      *
352      * \see enumValue()
353      */
354     MyClass& enumValueFromNullTerminatedArray(const char* const* values)
355     {
356         GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
357         enumValues_      = values;
358         enumValuesCount_ = -1;
359         return me();
360     }
361     /*! \brief
362      * Sets the default value using an index into the enumeration table.
363      *
364      * Cannot be specified without enumValue().
365      */
366     MyClass& defaultEnumIndex(int index)
367     {
368         GMX_ASSERT(index >= 0, "Invalid enumeration index");
369         defaultEnumIndex_ = index;
370         return me();
371     }
372
373 private:
374     //! Creates a StringOptionStorage object.
375     AbstractOptionStorage* createStorage(const OptionManagerContainer& managers) const override;
376
377     const char* const* enumValues_;
378     int                enumValuesCount_;
379     int                defaultEnumIndex_;
380
381     /*! \brief
382      * Needed to initialize StringOptionStorage from this class without
383      * otherwise unnecessary accessors.
384      */
385     friend class StringOptionStorage;
386 };
387
388 //! \}
389
390 namespace internal
391 {
392
393 /*! \internal
394  * \brief
395  * Type-specific implementation for IOptionValueStore for an enum option.
396  *
397  * This class is instantiated for each enum type for which EnumOption is used,
398  * and takes care of managing `int`-to-`enum` conversions.  Having this part in
399  * the header allows the actual storage implementation to not be in the header,
400  * which would require exposing all the internals through this one header...
401  *
402  * \ingroup module_options
403  */
404 template<typename EnumType>
405 class EnumIndexStore : public IOptionValueStore<int>
406 {
407 public:
408     //! Initializes the storage for the given actual enum variables.
409     EnumIndexStore(EnumType* store, std::vector<EnumType>* storeVector) :
410         store_(store),
411         storeVector_(storeVector)
412     {
413         if (storeVector_ != nullptr)
414         {
415             for (EnumType value : *storeVector_)
416             {
417                 intStore_.push_back(static_cast<int>(value));
418             }
419         }
420         else if (store_ != nullptr)
421         {
422             // TODO: Copy more than one value if that would make sense.
423             intStore_.push_back(static_cast<int>(store_[0]));
424         }
425     }
426
427     int           valueCount() override { return ssize(intStore_); }
428     ArrayRef<int> values() override { return intStore_; }
429     void          clear() override
430     {
431         intStore_.clear();
432         if (storeVector_ != nullptr)
433         {
434             storeVector_->clear();
435         }
436     }
437     void reserve(size_t count) override
438     {
439         intStore_.reserve(intStore_.size() + count);
440         if (storeVector_ != nullptr)
441         {
442             storeVector_->reserve(storeVector_->size() + count);
443         }
444     }
445     void append(const int& value) override
446     {
447         const size_t count = intStore_.size();
448         intStore_.push_back(value);
449         if (store_ != nullptr)
450         {
451             store_[count] = static_cast<EnumType>(value);
452         }
453         if (storeVector_ != nullptr)
454         {
455             storeVector_->push_back(static_cast<EnumType>(value));
456         }
457     }
458
459 private:
460     //! Stores the integer values for values().
461     std::vector<int>       intStore_;
462     EnumType*              store_;
463     std::vector<EnumType>* storeVector_;
464 };
465
466 //! \cond internal
467 /*! \internal
468  * \brief
469  * Helper to create EnumOptionStorage instances.
470  *
471  * This function works as a proxy between EnumOption::createStorage() and the
472  * EnumOptionStorage constructor, such that the latter does not need to be
473  * exposed in the header.
474  *
475  * \ingroup module_options
476  */
477 AbstractOptionStorage* createEnumOptionStorage(const AbstractOption& option,
478                                                const char* const*    enumValues,
479                                                int                   count,
480                                                int                   defaultValue,
481                                                int                   defaultValueIfSet,
482                                                std::unique_ptr<IOptionValueStore<int>> store);
483 //! \endcond
484
485 } // namespace internal
486
487 //! \addtogroup module_options
488 //! \{
489
490 /*! \brief
491 * Specifies an option that accepts an EnumerationArray of string values and writes the
492 * selected index into an `enum` variable.
493 *
494 * \tparam EnumType  DataType of the variable that receives the values
495 *
496 * Examples:
497 * \code
498   enum class MyEnum { Atom, Res, Mol, Count } : int;
499   EnumerationArray<MyEnum, const char *> myEnumNames = { "atom", "residue", "molecule" };
500   MyEnum       value = MyEnum::Atom; // default value
501   options.addOption(EnumOption<MyEnum>("type").enumValue(myEnumNames).store(&value));
502 * \endcode
503 *
504 * storeCount() is not currently implemented for this option type, and
505 * providing multiple default values through an array passed to store() does
506 * not work consistently in all cases.
507 * In the current implementation, the values of the enum type should correspond
508 * to indices in the array passed to enumValue(), i.e., be consecutive
509 * starting from zero.  Only values corresponding to valid indices are accepted
510 * as parameters to, e.g., defaultValue().  However, other values can be used
511 * as the initial value of the variable (`value` in the above example), and
512 * those will be preserved if the option is not set.
513 *
514 * Public methods in this class do not throw.
515 *
516 * \inpublicapi
517 */
518 template<typename EnumType>
519 class EnumOption : public OptionTemplate<EnumType, EnumOption<EnumType>>
520 {
521 public:
522     //! OptionInfo subclass corresponding to this option type.
523     typedef EnumOptionInfo InfoType;
524
525     // This needs to be duplicated from OptionTemplate because this class
526     // is a template.
527     //! Short-hand for the base class.
528     typedef OptionTemplate<EnumType, EnumOption<EnumType>> MyBase;
529
530     //! Initializes an option with the given name.
531     explicit EnumOption(const char* name) : MyBase(name), enumValues_(nullptr), enumValuesCount_(0)
532     {
533     }
534
535     /*! \brief
536      * Sets the option to only accept one of a fixed set of strings.
537      *
538
539      * \param[in] values  Array of strings to accept.
540      *
541      * Also accepts prefixes of the strings; if a prefix matches more than
542      * one of the possible strings, the shortest one is used (in a tie, the
543      * first one is).
544      *
545      * The strings are copied once the option is created.
546      */
547     EnumOption& enumValue(const EnumerationArray<EnumType, const char*>& values)
548     {
549         GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
550         enumValues_      = values.data();
551         enumValuesCount_ = values.size();
552         return MyBase::me();
553     }
554
555 private:
556     //! Helper function to convert default values for storage initialization.
557     static int convertToInt(const EnumType* defaultValue)
558     {
559         return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
560     }
561
562     //! Creates a EnumOptionStorage object.
563     AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override
564     {
565         // TODO: Implement storeCount() if necessary.
566         return internal::createEnumOptionStorage(*this,
567                                                  enumValues_,
568                                                  enumValuesCount_,
569                                                  convertToInt(MyBase::defaultValue()),
570                                                  convertToInt(MyBase::defaultValueIfSet()),
571                                                  std::make_unique<internal::EnumIndexStore<EnumType>>(
572                                                          MyBase::store(), MyBase::storeVector()));
573     }
574
575     const char* const* enumValues_;
576     int                enumValuesCount_;
577
578     /*! \brief
579      * Needed to initialize EnumOptionStorage from this class without
580      * otherwise unnecessary accessors.
581      */
582     friend class EnumOptionStorage;
583 };
584
585 /*! \brief
586 * Specifies an option that accepts enumerated string values and writes the
587 * selected index into an `enum` variable.
588 *
589 * \tparam EnumType  Type of the variable that receives the values
590 *     (can also be `int`).
591 *
592 * Examples:
593 * \code
594   enum MyEnum { eAtom, eRes, eMol };
595   using gmx::LegacyEnumOption;
596   const char * const  allowed[] = { "atom", "residue", "molecule" };
597   MyEnum       value = eAtom; // default value
598   options.addOption(LegacyEnumOption<MyEnum>("type").enumValue(allowed).store(&value));
599 * \endcode
600 *
601 * Works exactly as EnumOption.
602 *
603 * This is legacy support for pargsToOptions and can be removed when it
604 * is removed.  No new uses of it should be made.
605 *
606 * Public methods in this class do not throw.
607 *
608 * \inpublicapi
609 */
610 template<typename EnumType>
611 class LegacyEnumOption : public OptionTemplate<EnumType, LegacyEnumOption<EnumType>>
612 {
613 public:
614     //! OptionInfo subclass corresponding to this option type.
615     typedef EnumOptionInfo InfoType;
616
617     // This needs to be duplicated from OptionTemplate because this class
618     // is a template.
619     //! Short-hand for the base class.
620     typedef OptionTemplate<EnumType, LegacyEnumOption<EnumType>> MyBase;
621
622     //! Initializes an option with the given name.
623     explicit LegacyEnumOption(const char* name) :
624         MyBase(name),
625         enumValues_(nullptr),
626         enumValuesCount_(0)
627     {
628     }
629
630     /*! \brief
631      * Sets the option to only accept one of a fixed set of strings.
632      *
633      * \param[in] values  Array of strings to accept.
634      *
635      * Also accepts prefixes of the strings; if a prefix matches more than
636      * one of the possible strings, the shortest one is used (in a tie, the
637      * first one is).
638      *
639      * The strings are copied once the option is created.
640      */
641     template<size_t count>
642     LegacyEnumOption& enumValue(const char* const (&values)[count])
643     {
644         GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
645         enumValues_      = values;
646         enumValuesCount_ = count;
647         return MyBase::me();
648     }
649     /*! \brief
650      * Sets the option to only accept one of a fixed set of strings.
651      *
652      * \param[in] values  Array of strings to accept, with a NULL pointer
653      *      following the last string.
654      *
655      * Works otherwise as the array version, but accepts a pointer to
656      * an array of undetermined length.  The end of the array is indicated
657      * by a NULL pointer in the array.
658      *
659      * \see enumValue()
660      */
661     LegacyEnumOption& enumValueFromNullTerminatedArray(const char* const* values)
662     {
663         GMX_ASSERT(enumValues_ == nullptr, "Multiple sets of enumerated values specified");
664         enumValues_      = values;
665         enumValuesCount_ = -1;
666         return MyBase::me();
667     }
668
669 private:
670     //! Helper function to convert default values for storage initialization.
671     static int convertToInt(const EnumType* defaultValue)
672     {
673         return defaultValue != nullptr ? static_cast<int>(*defaultValue) : -1;
674     }
675
676     //! Creates a EnumOptionStorage object.
677     AbstractOptionStorage* createStorage(const OptionManagerContainer& /*managers*/) const override
678     {
679         // TODO: Implement storeCount() if necessary.
680         return internal::createEnumOptionStorage(*this,
681                                                  enumValues_,
682                                                  enumValuesCount_,
683                                                  convertToInt(MyBase::defaultValue()),
684                                                  convertToInt(MyBase::defaultValueIfSet()),
685                                                  std::make_unique<internal::EnumIndexStore<EnumType>>(
686                                                          MyBase::store(), MyBase::storeVector()));
687     }
688
689     const char* const* enumValues_;
690     int                enumValuesCount_;
691
692     /*! \brief
693      * Needed to initialize EnumOptionStorage from this class without
694      * otherwise unnecessary accessors.
695      */
696     friend class EnumOptionStorage;
697 };
698
699 /*! \brief
700  * Wrapper class for accessing boolean option information.
701  *
702  * \inpublicapi
703  */
704 class BooleanOptionInfo : public OptionInfo
705 {
706 public:
707     //! Creates an option info object for the given option.
708     explicit BooleanOptionInfo(BooleanOptionStorage* option);
709
710     //! Returns the default value for this option.
711     bool defaultValue() const;
712
713 private:
714     const BooleanOptionStorage& option() const;
715 };
716
717 /*! \brief
718  * Wrapper class for accessing integer option information.
719  *
720  * \inpublicapi
721  */
722 class IntegerOptionInfo : public OptionInfo
723 {
724 public:
725     //! Creates an option info object for the given option.
726     explicit IntegerOptionInfo(IntegerOptionStorage* option);
727 };
728
729 /*! \brief
730  * Wrapper class for accessing 64-bit integer option information.
731  *
732  * \inpublicapi
733  */
734 class Int64OptionInfo : public OptionInfo
735 {
736 public:
737     //! Creates an option info object for the given option.
738     explicit Int64OptionInfo(Int64OptionStorage* option);
739 };
740
741 /*! \brief
742  * Wrapper class for accessing floating-point option information.
743  *
744  * \inpublicapi
745  */
746 class DoubleOptionInfo : public OptionInfo
747 {
748 public:
749     //! Creates an option info object for the given option.
750     explicit DoubleOptionInfo(DoubleOptionStorage* option);
751
752     //! Whether the option specifies a time value.
753     bool isTime() const;
754
755     /*! \brief
756      * Sets a scale factor for user-provided values.
757      *
758      * Any user-provided value is scaled by the provided factor.
759      * Programmatically set default values are not scaled.
760      * If called multiple times, later calls override the previously set
761      * value.  In other words, the scaling is not cumulative.
762      */
763     void setScaleFactor(double factor);
764
765 private:
766     DoubleOptionStorage&       option();
767     const DoubleOptionStorage& option() const;
768 };
769
770 /*! \brief
771  * Wrapper class for accessing floating-point option information.
772  *
773  * \inpublicapi
774  */
775 class FloatOptionInfo : public OptionInfo
776 {
777 public:
778     //! Creates an option info object for the given option.
779     explicit FloatOptionInfo(FloatOptionStorage* option);
780
781     //! Whether the option specifies a time value.
782     bool isTime() const;
783
784     //! \copydoc DoubleOptionInfo::setScaleFactor()
785     void setScaleFactor(double factor);
786
787 private:
788     FloatOptionStorage&       option();
789     const FloatOptionStorage& option() const;
790 };
791
792 /*! \brief
793  * Wrapper class for accessing string option information.
794  *
795  * \inpublicapi
796  */
797 class StringOptionInfo : public OptionInfo
798 {
799 public:
800     //! Creates an option info object for the given option.
801     explicit StringOptionInfo(StringOptionStorage* option);
802
803     /*! \brief
804      * Whether this option accepts an enumerated set of values.
805      *
806      * Returns true if StringOption::enumValues() was used when creating
807      * this option.
808      */
809     bool isEnumerated() const;
810     /*! \brief
811      * Returns the set of allowed values for this option.
812      *
813      * Returns an empty vector if isEnumerated() returns false.
814      */
815     const std::vector<std::string>& allowedValues() const;
816
817 private:
818     const StringOptionStorage& option() const;
819 };
820
821 /*! \brief
822  * Wrapper class for accessing enum option information.
823  *
824  * \inpublicapi
825  */
826 class EnumOptionInfo : public OptionInfo
827 {
828 public:
829     //! Creates an option info object for the given option.
830     explicit EnumOptionInfo(EnumOptionStorage* option);
831
832     /*! \brief
833      * Returns the set of allowed values for this option.
834      */
835     const std::vector<std::string>& allowedValues() const;
836
837 private:
838     const EnumOptionStorage& option() const;
839 };
840
841 /*! \typedef RealOption
842  * \brief
843  * Typedef for either DoubleOption or FloatOption, depending on precision.
844  *
845  * Generally, new would be better using DoubleOption, but this is provided for
846  * cases where the output value needs to be of type `real` for some reason.
847  */
848 /*! \typedef RealOptionInfo
849  * \brief
850  * Typedef for either DoubleOptionInfo or FloatOptionInfo, depending on precision.
851  *
852  * Generally, new would be better using DoubleOption, but this is provided for
853  * cases where the output value needs to be of type `real` for some reason.
854  */
855 #if GMX_DOUBLE
856 typedef DoubleOption     RealOption;
857 typedef DoubleOptionInfo RealOptionInfo;
858 #else
859 typedef FloatOption     RealOption;
860 typedef FloatOptionInfo RealOptionInfo;
861 #endif
862
863 //! \}
864
865 } // namespace gmx
866
867 #endif