deal.II version GIT relicensing-2055-gd703fda1ad 2024-10-30 20:00:00+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
Public Member Functions | Static Public Member Functions | Public Attributes | Static Public Attributes | Protected Attributes | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes | List of all members
ParameterAcceptor Class Reference

#include <deal.II/base/parameter_acceptor.h>

Inheritance diagram for ParameterAcceptor:
Inheritance graph
[legend]

Public Member Functions

 ParameterAcceptor (const std::string &section_name="")
 
unsigned int get_acceptor_id () const
 
virtual ~ParameterAcceptor () override
 
virtual void declare_parameters (ParameterHandler &prm)
 
virtual void parse_parameters (ParameterHandler &prm)
 
std::string get_section_name () const
 
std::vector< std::string > get_section_path () const
 
template<typename ParameterType >
void add_parameter (const std::string &entry, ParameterType &parameter, const std::string &documentation="", ParameterHandler &prm_=prm, const Patterns::PatternBase &pattern= *Patterns::Tools::Convert< ParameterType >::to_pattern())
 
void enter_subsection (const std::string &subsection)
 
void leave_subsection ()
 
void enter_my_subsection (ParameterHandler &prm)
 
void leave_my_subsection (ParameterHandler &prm)
 
template<class Archive >
void serialize (Archive &ar, const unsigned int version)
 
EnableObserverPointer functionality

Classes derived from EnableObserverPointer provide a facility to subscribe to this object. This is mostly used by the ObserverPointer class.

void subscribe (std::atomic< bool > *const validity, const std::string &identifier="") const
 
void unsubscribe (std::atomic< bool > *const validity, const std::string &identifier="") const
 
unsigned int n_subscriptions () const
 
template<typename StreamType >
void list_subscribers (StreamType &stream) const
 
void list_subscribers () const
 

Static Public Member Functions

static void initialize (const std::string &filename="", const std::string &output_filename="", const ParameterHandler::OutputStyle output_style_for_output_filename=ParameterHandler::Short, ParameterHandler &prm=ParameterAcceptor::prm, const ParameterHandler::OutputStyle output_style_for_filename=ParameterHandler::DefaultStyle)
 
static void initialize (std::istream &input_stream, ParameterHandler &prm=ParameterAcceptor::prm)
 
static void clear ()
 
static void parse_all_parameters (ParameterHandler &prm=ParameterAcceptor::prm)
 
static void declare_all_parameters (ParameterHandler &prm=ParameterAcceptor::prm)
 
static ::ExceptionBaseExcInUse (int arg1, std::string arg2, std::string arg3)
 
static ::ExceptionBaseExcNoSubscriber (std::string arg1, std::string arg2)
 

Public Attributes

boost::signals2::signal< void()> declare_parameters_call_back
 
boost::signals2::signal< void()> parse_parameters_call_back
 

Static Public Attributes

static ParameterHandler prm
 

Protected Attributes

const std::string section_name
 
std::vector< std::string > subsections
 

Private Types

using map_value_type = decltype(counter_map)::value_type
 
using map_iterator = decltype(counter_map)::iterator
 

Private Member Functions

void check_no_subscribers () const noexcept
 

Static Private Member Functions

static unsigned int get_next_free_id ()
 

Private Attributes

const unsigned int acceptor_id
 
std::atomic< unsigned intcounter
 
std::map< std::string, unsigned intcounter_map
 
std::vector< std::atomic< bool > * > validity_pointers
 
const std::type_info * object_info
 

Static Private Attributes

static std::mutex class_list_mutex
 
static std::set< ParameterAcceptor *, internal::ParameterAcceptorCompareclass_list
 
static const char sep = '/'
 
static std::mutex mutex
 

Detailed Description

A parameter acceptor base class. This class is used to define a public interface for classes which want to use a single global ParameterHandler to handle parameters. This class declares one static ParameterHandler, and two static functions (declare_all_parameters() and parse_all_parameters()) that manage all of the derived classes.

The basic interface provides two subscription mechanisms: a global subscription mechanism and a local subscription mechanism.

The global subscription mechanism is such that whenever an object of a class derived from ParameterAcceptor is created, then a pointer to that object-of-derived-type is registered, together with a path in the parameter file.

Such registry is traversed upon invocation of the single function ParameterAcceptor::initialize("file.prm") which in turn calls the method ParameterAcceptor::declare_parameters() for each of the registered classes, reads the file file.prm and subsequently calls the method ParameterAcceptor::parse_parameters(), again for each of the registered classes. The method log_info() can be used to extract information about the classes that have been derived from ParameterAcceptor, and that will be parsed when calling ParameterAcceptor::initialize().

ParameterAcceptor can be used in three different ways: by overloading the ParameterAcceptor::declare_parameters() and ParameterAcceptor::parse_parameters() methods, by calling its ParameterAcceptor::add_parameter() method for each parameter we want to have, or by constructing a ParameterAcceptorProxy class with your own class, provided that your class implements the declare_parameters and parse_parameters functions (the first can be a static member in this case).

By using the add_parameter method, ParameterAcceptor makes sure that the given parameter is registered in the global parameter handler (by calling ParameterHandler::add_parameter()), at the correct path. If you define all your parameters using the ParameterAcceptor::add_parameter() method, then you don't need to overload any of the virtual methods of this class.

If some post processing is required on the parsed values, the user can attach a signal to ParameterAcceptor::declare_parameters_call_back and ParameterAcceptor::parse_parameters_call_back, that are called just after the declare_parameters() and parse_parameters() functions of each derived class. step-69 has an example of doing this.

A typical usage of this class is the following:

// This is your own class, derived from ParameterAcceptor
class MyClass : public ParameterAcceptor
{
// The constructor of ParameterAcceptor requires a std::string,
// which defines the section name where the parameters of MyClass
// will be stored.
MyClass()
: ParameterAcceptor("Some class name")
{
add_parameter("A param", member_var);
}
private:
std::vector<unsigned int> member_var;
...
};
int main()
{
// Make sure you create your object BEFORE calling
// ParameterAcceptor::initialize()
MyClass class;
// With this call, all derived classes will have their
// parameters initialized
}
static void initialize(const std::string &filename="", const std::string &output_filename="", const ParameterHandler::OutputStyle output_style_for_output_filename=ParameterHandler::Short, ParameterHandler &prm=ParameterAcceptor::prm, const ParameterHandler::OutputStyle output_style_for_filename=ParameterHandler::DefaultStyle)

An implementation that uses user defined declare and parse functions is given by the following example:

// Again your own class, derived from ParameterAcceptor
//
// If you don't pass anything to the constructor of
// ParameterAcceptor, then the class name is used, "MyClass"
// in this case
class MyClass : public ParameterAcceptor
{
virtual void declare_parameters(ParameterHandler &prm)
{
...
}
virtual void parse_parameters(ParameterHandler &prm)
{
...
}
};
int main()
{
// Make sure you create your object BEFORE calling
// ParameterAcceptor::initialize()
MyClass class;
class.run();
}

Parameter files can be organised into section/subsection/subsubsection. To do so, the std::string passed to ParameterAcceptor within the constructor of the derived class needs to contain the separator "/". In fact, "first/second/third/My Class" will organize the parameters as follows

subsection first
subsection second
subsection third
subsection My Class
... # all the parameters
end
end
end
end
Point< 2 > second
Definition grid_out.cc:4624
Point< 2 > first
Definition grid_out.cc:4623

In the following examples, we propose some use cases with increasing complexities.

MyClass is derived from ParameterAcceptor and has a member object that is derived itself from ParameterAcceptor.

class MyClass : public ParameterAcceptor
{
MyClass (std::string name);
virtual void declare_parameters(ParameterHandler &prm);
private:
SomeParsedClass<dim> my_subclass;
...
};
MyClass::MyClass(std::string name)
, my_subclass("Forcing term")
{}
void MyClass::declare_parameters(ParameterHandler &prm)
{
// many add_parameter(...);
}
...
int main()
{
MyClass mc("My Class");
}

In this case, the structure of the parameters will be

subsection Forcing term
... #parameters of SomeParsedClass
end
subsection My class
... #all the parameters of MyClass defined in declare_parameters
end
virtual void declare_parameters(ParameterHandler &prm)

Now suppose that in the main file we need two or more objects of MyClass

int main()
{
MyClass ca("Class A");
MyClass cb("Class B");
}

What we will read in the parameter file looks like

subsection Class A
...
end
subsection Class B
...
end
subsection Forcing term
...
end

Note that there is only one section "Forcing term", this is because both objects have defined the same name for the section of their SomeParsedClass. There are two strategies to change this behavior. The first one (not recommended) would be to change the name of the section of SomeParsedClass such that it contains also the string passed to the constructor of MyClass:

MyClass::MyClass(std::string name)
, my_subclass(name+" --- forcing term")
{}

The other way to proceed (recommended) is to use exploit the /section/subsection approach in the main class.

int main()
{
MyClass ca("/Class A/Class");
MyClass cb("/Class B/Class");
}

Now, in the parameter file we can find

subsection Class A
subsection Class
...
end
subsection Forcing term
...
end
end
subsection Class B
subsection Class
...
end
subsection Forcing term
...
end
end

Note the "/" at the begin of the string name. This is interpreted by ParameterAcceptor like the root folder in Unix systems. The sections "Class A" and "Class B" will not be nested under any section. On the other hand, if the string does not begin with a "/" as in the previous cases the section will be created under the current path, which depends on the previously defined sections/subsections/subsubsections. Indeed, the section "Forcing term" is nested under "Class A" or "Class B". To make things more clear. let's consider the following two examples

int main()
{
MyClass ca("/Class A/Class");
MyClass cb("Class B/Class");
}

The parameter file will have the following structure

subsection Class A
subsection Class
...
end
subsection Forcing term
...
end
subsection Class B
subsection Class
...
end
subsection Forcing term
...
end
end
end

If instead one of the paths ends with "/" instead of just a name of the class, subsequent classes will interpret this as a full path, interpreting the class name as a directory name:

int main()
{
MyClass ca("/Class A/Class/");
MyClass cb("Class B/Class");
}

The parameter file will have the following structure

subsection Class A
subsection Class
...
subsection Forcing term
...
end
subsection Class B
subsection Class
...
end
subsection Forcing term
...
end
end
end
end

As a final remark, in order to allow a proper management of all the sections/subsections, the instantiation of objects and the call to ParameterAcceptor::initialize() cannot be done on multiple, concurrently running threads.

If you pass an empty name, the boost::core::demangle() function is used to fill the section name with a human readable version of the class name itself.

See the tutorial program step-60 for an example on how to use this class.

Definition at line 358 of file parameter_acceptor.h.

Member Typedef Documentation

◆ map_value_type

using EnableObserverPointer::map_value_type = decltype(counter_map)::value_type
privateinherited

The data type used in counter_map.

Definition at line 238 of file enable_observer_pointer.h.

◆ map_iterator

using EnableObserverPointer::map_iterator = decltype(counter_map)::iterator
privateinherited

The iterator type used in counter_map.

Definition at line 243 of file enable_observer_pointer.h.

Constructor & Destructor Documentation

◆ ParameterAcceptor()

ParameterAcceptor::ParameterAcceptor ( const std::string &  section_name = "")

The constructor adds derived classes to the list of acceptors. If a section name is specified, then this is used to scope the parameters in the given section, otherwise a pretty printed version of the derived class is used.

Definition at line 49 of file parameter_acceptor.cc.

◆ ~ParameterAcceptor()

ParameterAcceptor::~ParameterAcceptor ( )
overridevirtual

Destructor.

Definition at line 59 of file parameter_acceptor.cc.

Member Function Documentation

◆ get_acceptor_id()

unsigned int ParameterAcceptor::get_acceptor_id ( ) const
inline

Get the acceptor id of this object.

Definition at line 275 of file parameter_acceptor.cc.

◆ initialize() [1/2]

void ParameterAcceptor::initialize ( const std::string &  filename = "",
const std::string &  output_filename = "",
const ParameterHandler::OutputStyle  output_style_for_output_filename = ParameterHandler::Short,
ParameterHandler prm = ParameterAcceptor::prm,
const ParameterHandler::OutputStyle  output_style_for_filename = ParameterHandler::DefaultStyle 
)
static

Call declare_all_parameters(), read the parameters from filename (only if filename is a non-empty string), and then call parse_all_parameters().

If the parameter filename is the empty string, then no attempt to read a parameter file is done. This may be useful if you are ok with using default values, and don't want to read external files to use a class derived from ParameterAcceptor.

If output_filename is not the empty string, then we write the content that was read into the output_filename file, using the style specified in output_style_for_output_filename. The format of both input and output files are selected using the extensions of the files themselves. This can be either prm, xml, or json for the filename, and any of the supported formats for the output_filename.

If the input file does not exist, a default one with the same name is created for you following the style specified in output_style_for_filename, and an exception is thrown.

By default, the file format used to write the files is deduced from the extension of the file names. If the corresponding ParameterHandler::OutputStyle specifies a format specification, this must be compatible with the file extension, or an exception will be thrown.

If the extension is not recognized, and you do not specify a format in the corresponding ParameterHandler::OutputStyle, an assertion is thrown.

Parameters
filenameInput file name
output_filenameOutput file name
output_style_for_output_filenameHow to write the output file
prmThe ParameterHandler to use
output_style_for_filenameHow to write the default input file if it does not exist

Definition at line 80 of file parameter_acceptor.cc.

◆ initialize() [2/2]

void ParameterAcceptor::initialize ( std::istream &  input_stream,
ParameterHandler prm = ParameterAcceptor::prm 
)
static

Call declare_all_parameters(), read the parameters from the input_stream in prm format, and then call parse_all_parameters().

An exception is thrown if the input_stream is invalid.

Parameters
input_streamInput stream
prmThe ParameterHandler to use

Definition at line 114 of file parameter_acceptor.cc.

◆ clear()

void ParameterAcceptor::clear ( )
static

Clear class list and global parameter file.

Definition at line 126 of file parameter_acceptor.cc.

◆ declare_parameters()

void ParameterAcceptor::declare_parameters ( ParameterHandler prm)
virtual

Derived classes can use this method to declare their parameters. ParameterAcceptor::initialize() calls it for each derived class. The default implementation is empty.

Reimplemented in ParameterAcceptorProxy< SourceClass >.

Definition at line 136 of file parameter_acceptor.cc.

◆ parse_parameters()

void ParameterAcceptor::parse_parameters ( ParameterHandler prm)
virtual

Derived classes can use this method to parse their parameters. ParameterAcceptor::initialize() calls it for each derived class. The default implementation is empty.

Reimplemented in ParameterAcceptorProxy< SourceClass >.

Definition at line 142 of file parameter_acceptor.cc.

◆ parse_all_parameters()

void ParameterAcceptor::parse_all_parameters ( ParameterHandler prm = ParameterAcceptor::prm)
static

Parse the given ParameterHandler. This function enters the subsection returned by get_section_name() for each derived class, and parses all parameters that were added using add_parameter().

Definition at line 148 of file parameter_acceptor.cc.

◆ declare_all_parameters()

void ParameterAcceptor::declare_all_parameters ( ParameterHandler prm = ParameterAcceptor::prm)
static

Initialize the global ParameterHandler with all derived classes parameters.This function enters the subsection returned by get_section_name() for each derived class, and declares all parameters that were added using add_parameter().

Definition at line 162 of file parameter_acceptor.cc.

◆ get_section_name()

std::string ParameterAcceptor::get_section_name ( ) const

Return the section name of this class. If a name was provided at construction time, then that name is returned, otherwise it returns the demangled name of this class.

Definition at line 71 of file parameter_acceptor.cc.

◆ get_section_path()

std::vector< std::string > ParameterAcceptor::get_section_path ( ) const

Traverse all registered classes, and figure out what subsections we need to enter.

Definition at line 176 of file parameter_acceptor.cc.

◆ add_parameter()

template<typename ParameterType >
void ParameterAcceptor::add_parameter ( const std::string &  entry,
ParameterType &  parameter,
const std::string &  documentation = "",
ParameterHandler prm_ = prm,
const Patterns::PatternBase pattern = *Patterns::Tools::Convert<ParameterType>::to_pattern() 
)

Add a parameter in the correct path. This method forwards all arguments to the prm.add_parameter() method, after entering the correct section path. By default it uses the ParameterAcceptor::prm variable as ParameterHandler.

See the documentation of ParameterHandler::add_parameter() for more information.

Definition at line 727 of file parameter_acceptor.h.

◆ enter_subsection()

void ParameterAcceptor::enter_subsection ( const std::string &  subsection)

Add the given subsection to the global path stored in this class.

This function changes the behavior of enter_my_subsection(), by appending a new subsection to the path stored in this class.

This method can be used to split the parameters of this class into subsections, while still maintaining the general behavior of this class.

An example usage is given by the following snippet:

class MyClass : public ParameterAcceptor
{
MyClass()
: ParameterAcceptor("Main section")
{
add_parameter("A param", member_var);
enter_subsection("New section");
add_parameter("Another param", another_member_var);
leave_subsection();
}
private:
std::vector<unsigned int> member_var = {1,2};
std::map<types::boundary_id, std::string> another_member_var;
...
};
int main()
{
// ParameterAcceptor::initialize()
MyClass class;
// With this call, all derived classes will have their
// parameters initialized
}

which will produce a parameter file organized as

subsection Main section
set A param = 1, 2
subsection New section
set Another param =
end
end

Definition at line 224 of file parameter_acceptor.cc.

◆ leave_subsection()

void ParameterAcceptor::leave_subsection ( )

Leave the subsection that was entered by calling the enter_subsection() function.

Definition at line 239 of file parameter_acceptor.cc.

◆ enter_my_subsection()

void ParameterAcceptor::enter_my_subsection ( ParameterHandler prm = ParameterAcceptor::prm)

Make sure we enter the right subsection of the given parameter.

Definition at line 249 of file parameter_acceptor.cc.

◆ leave_my_subsection()

void ParameterAcceptor::leave_my_subsection ( ParameterHandler prm = ParameterAcceptor::prm)

This function undoes what the enter_my_subsection() function did. It only makes sense if enter_my_subsection() was called on prm before this one.

Definition at line 262 of file parameter_acceptor.cc.

◆ get_next_free_id()

unsigned int ParameterAcceptor::get_next_free_id ( )
staticprivate

Get the next free id for this class.

Definition at line 283 of file parameter_acceptor.cc.

◆ subscribe()

void EnableObserverPointer::subscribe ( std::atomic< bool > *const  validity,
const std::string &  identifier = "" 
) const
inherited

Subscribes a user of the object by storing the pointer validity. The subscriber may be identified by text supplied as identifier.

Definition at line 131 of file enable_observer_pointer.cc.

◆ unsubscribe()

void EnableObserverPointer::unsubscribe ( std::atomic< bool > *const  validity,
const std::string &  identifier = "" 
) const
inherited

Unsubscribes a user from the object.

Note
The identifier and the validity pointer must be the same as the one supplied to subscribe().

Definition at line 151 of file enable_observer_pointer.cc.

◆ n_subscriptions()

unsigned int EnableObserverPointer::n_subscriptions ( ) const
inlineinherited

Return the present number of subscriptions to this object. This allows to use this class for reference counted lifetime determination where the last one to unsubscribe also deletes the object.

Definition at line 322 of file enable_observer_pointer.h.

◆ list_subscribers() [1/2]

template<typename StreamType >
void EnableObserverPointer::list_subscribers ( StreamType &  stream) const
inlineinherited

List the subscribers to the input stream.

Definition at line 339 of file enable_observer_pointer.h.

◆ list_subscribers() [2/2]

void EnableObserverPointer::list_subscribers ( ) const
inherited

List the subscribers to deallog.

Definition at line 199 of file enable_observer_pointer.cc.

◆ serialize()

template<class Archive >
void EnableObserverPointer::serialize ( Archive &  ar,
const unsigned int  version 
)
inlineinherited

Read or write the data of this object to or from a stream for the purpose of serialization using the BOOST serialization library.

This function does not actually serialize any of the member variables of this class. The reason is that what this class stores is only who subscribes to this object, but who does so at the time of storing the contents of this object does not necessarily have anything to do with who subscribes to the object when it is restored. Consequently, we do not want to overwrite the subscribers at the time of restoring, and then there is no reason to write the subscribers out in the first place.

Definition at line 331 of file enable_observer_pointer.h.

◆ check_no_subscribers()

void EnableObserverPointer::check_no_subscribers ( ) const
privatenoexceptinherited

Check that there are no objects subscribing to this object. If this check passes then it is safe to destroy the current object. It this check fails then this function will either abort or print an error message to deallog (by using the AssertNothrow mechanism), but will not throw an exception.

Note
Since this function is just a consistency check it does nothing in release mode.
If this function is called when there is an uncaught exception then, rather than aborting, this function prints an error message to the standard error stream and returns.

Definition at line 53 of file enable_observer_pointer.cc.

Member Data Documentation

◆ declare_parameters_call_back

boost::signals2::signal<void()> ParameterAcceptor::declare_parameters_call_back

Declare parameter call back. This signal is triggered right after declare_parameters() has been called, to allow users to prepare their variables right after parameters have been declared. The default implementation is empty.

Definition at line 459 of file parameter_acceptor.h.

◆ parse_parameters_call_back

boost::signals2::signal<void()> ParameterAcceptor::parse_parameters_call_back

Parse parameter call back. This function is called at the end of parse_parameters(), to allow users to process their parameters right after they have been parsed. The default implementation is empty.

You can use this function, for example, to create a quadrature rule after you have read how many quadrature points you wanted to use from the parameter file.

Definition at line 478 of file parameter_acceptor.h.

◆ prm

ParameterHandler ParameterAcceptor::prm
static

The global parameter handler.

Definition at line 533 of file parameter_acceptor.h.

◆ class_list_mutex

std::mutex ParameterAcceptor::class_list_mutex
staticprivate

A mutex to prevent writing on the class_list set from multiple threads.

Definition at line 619 of file parameter_acceptor.h.

◆ class_list

std::set< ParameterAcceptor *, internal::ParameterAcceptorCompare > ParameterAcceptor::class_list
staticprivate

A set containing the address of all constructed classes of type ParameterAcceptor.

Definition at line 626 of file parameter_acceptor.h.

◆ acceptor_id

const unsigned int ParameterAcceptor::acceptor_id
private

The id of this specific class instance.

Definition at line 629 of file parameter_acceptor.h.

◆ sep

const char ParameterAcceptor::sep = '/'
staticprivate

Separator between sections.

Definition at line 634 of file parameter_acceptor.h.

◆ section_name

const std::string ParameterAcceptor::section_name
protected

The subsection name for this class.

Definition at line 638 of file parameter_acceptor.h.

◆ subsections

std::vector<std::string> ParameterAcceptor::subsections
protected

The subsubsections that are currently active.

Definition at line 641 of file parameter_acceptor.h.

◆ counter

std::atomic<unsigned int> EnableObserverPointer::counter
mutableprivateinherited

Store the number of objects which subscribed to this object. Initially, this number is zero, and upon destruction it shall be zero again (i.e. all objects which subscribed should have unsubscribed again).

The creator (and owner) of an object is counted in the map below if HE manages to supply identification.

We use the mutable keyword in order to allow subscription to constant objects also.

This counter may be read from and written to concurrently in multithreaded code: hence we use the std::atomic class template.

Definition at line 227 of file enable_observer_pointer.h.

◆ counter_map

std::map<std::string, unsigned int> EnableObserverPointer::counter_map
mutableprivateinherited

In this map, we count subscriptions for each different identification string supplied to subscribe().

Definition at line 233 of file enable_observer_pointer.h.

◆ validity_pointers

std::vector<std::atomic<bool> *> EnableObserverPointer::validity_pointers
mutableprivateinherited

In this vector, we store pointers to the validity bool in the ObserverPointer objects that subscribe to this class.

Definition at line 249 of file enable_observer_pointer.h.

◆ object_info

const std::type_info* EnableObserverPointer::object_info
mutableprivateinherited

Pointer to the typeinfo object of this object, from which we can later deduce the class name. Since this information on the derived class is neither available in the destructor, nor in the constructor, we obtain it in between and store it here.

Definition at line 257 of file enable_observer_pointer.h.

◆ mutex

std::mutex EnableObserverPointer::mutex
staticprivateinherited

A mutex used to ensure data consistency when accessing the mutable members of this class. This lock is used in the subscribe() and unsubscribe() functions, as well as in list_subscribers().

Definition at line 280 of file enable_observer_pointer.h.


The documentation for this class was generated from the following files: