(i'm using Visual C+++ 2010)
suppose i have defined a tuple like this:
typedef std::tr1::tuple<
int //i want to set its default value to 9
, double //i want to set its default value to 3.3
, int //i want to set its default value to 2
, double //i want to set its default value to -7.2
> Mytuple;
i can do that in a struct. but i wonder if it is possible to do that in std::tr1::tuple.
Besides, i want to know when shoud i use std::tr1:tuple or struct?
anyone can help me?
A tuple is not a magical replacement for a struct. Their purposes are very different. A struct is, first and foremost, a language construct. A tuple is a library construct.
Structs get to have default values because the language says that you can write constructors to give them default values. The language then takes responsibility to call that constructor to initialize the struct. tuple, as a library construct, has no such capabilities, anymore than you can give std::vector<T> a default T that it will always automatically use. You can provide initial values for each member, but you can't give it defaults.
And if you think about it, you wouldn't want to. Imagine if someone could say that every tuple<int, float> was always created with 3 and 54.221. Even if some other code created it that knew nothing about this rule, it would have to be followed, (just as constructors for the type are used everywhere that type is used). Remember: every tuple<int, float> is the same type.
Really, a tuple is a substitute for the inability to perform reflection on a struct and do compile-time iteration over its members. The other main reason they exist is to be able to have compile-time dynamic structures (that is, the ability to create aggregates of types based on compile-time arguments, rather than a static list directly written into a file).
So unless you need to use std::tie (for effectively returning multiple values), iteration over members (ie: call some template function for each member of an object), or some similar specialized code, you should be using a struct.
Related
I know that c and c++ standards state that if you don't specify first element's value a start value of enum will default to 0.
But e.g. in Linux kernel sources I faced strange declarations dozens of times. e.g. numa_faults_stats:
enum numa_faults_stats {
NUMA_MEM = 0,
NUMA_CPU,
NUMA_MEMBUF,
NUMA_CPUBUF
};
What is the need for explicitly set first element of this enum to 0?
Related post.
There are very many rules for various things in C and C++: this being one of them. Sometimes it's nice to be explicit, for clarity.
Another common one is to use variable names in function prototypes (only the types are needed). Yet another is a return 0; in main in either language. The explicit use of public and private in a C++ class or struct is another.
You can use enums without care its value like only using it comprasions with each other. But sometimes its value is important. You may use is as an index of an array. eg.
struct NUMA Numa[N];
Numa[NUMA_MEM];
Numa[NUMA_CPU];
In this case it is definitly good idea explicitly assing value even it is default equal. You emphasize that its value has usage in code.
I have an old C library I try to modify. There is a line like:
memcpy(&m_agents[idx].params, params, sizeof(dtCrowdAgentParams));
And ofcourse C stule pod like values and structs get copied. But I tried to add to params.some_struct.some_inner_map_field std::map and it does not get initialised on memcpy.
So I wonder how to copy my map keeping it alive? (if possible not extending methods of params and params.some_struct)
I would need to see the full definition of the struct to be sure, but this should work:
m_agents[idx].params = *params;
For POD types, it will do the same thing as memcpy. For non-POD types, it will call their assignment operator.
Replacing it with
m_agents[idx].params = *params;
will correct that instance. However, it's reasonable to suppose that the C library you are working with is assuming POD throughout and so you will need to check the whole codebase to ensure it's not doing anything that will break things elsewhere.
Are your maps mutable within the library or can you treat them as constant while the library is handling the data? If you can treat them as constant consider passing a handle, or pointer, to you map into the library instead of including the map itself in the parameter struct.
so i use BOOST.EXTENTION to load modules. I have a special file that describes each module. I read variables from that file.
so such example:
shared_library m("my_module_name");
// Call a function that returns an int and takes a float parameter.
int result = m.get<int, float>("function_name")(5.0f);
m.close();
for me would turn into:
shared_library m("my_module_name");
// Call a function that returns an int and takes a float parameter.
int result = m.get<myMap["TYPE_1_IN_STRING_FORM"], myMap["TYPE_2_IN_STRING_FORM"]>("function_name")(5.0f);
m.close();
How to create such map that would map standard and costume types?
Update:
may be with variant:
shared_library m("my_module_name");
int result = m.get<boost::variant< int, float, ... other types we want to support >, boost::variant< int, float, ... other types we want to support > >("function_name")(5.0f);
m.close();
can halp? so we would not care as long as all types we want are declared in it?
For that, you would need a heterogeneous map - that is, its elements can be of different types. Furthermore you would need the ability to return types from functions, not just variables.
Now, a heterogeneous map would be possible with Boost.Variant or a simple union, but that binds it to compile time: we need to know every type that is possible to create that variant/union.
Of course a Boost.Any would be possible to store everything and its dog, but the problem strikes again: you need to extract the real type out of that Boost.Any again. The problem repeats itself. And if you know the real type, you can aswell just make a variant/union and save yourself the any_cast trouble.
Now, for another troublesome thing:
m.get<myMap["TYPE_1_IN_STRING_FORM"], myMap["TYPE_2_IN_STRING_FORM"]>
To make the above line work, you'd need two features that C++ doesn't have: the ability to return types and runtime templates. Lets ignore the first point for a moment.
Templates are compile-time, and the get function is such a template. Now, to use that template, your myMap would need to be able to return types at compile-time, while getting populated at runtime. See the contradiction? That's why runtime templates would be needed.
Sadly, exactly those three things are not possible (or extremely hard and very very limited) in C++ at runtime: heterogeneous data types (without constant size), returning types and templates.
Everything that involves types needs to be done at compile-time. This blogpost by #Gman somewhat correlates with that problem. It's definitly worth a read if you want to know what C++ just can't do.
So, to conclude: You'll need to rethink and refactor your problem and solution. :|
I have really heavy task to achieve and I haven't found any solution good enough. So, here is the description:
- task is to evaluate multiple single dimension arrays which number can vary
- good news is that it is possible to specify types of arrays
And desirable way of doing it:
- creating a class with constructor that accepts variable number of arrays
- these arrays should be also used as properties (private members), so multiple operations can be done on(with) them during lifecycle of object
How I tried to do it:
- constructor member function with variable number of paramaters (I'm not sure why this doesn't work)
- constructor with vector should be better way, but how to store arrays that type is specified in separate array, meaning you can't expect certain datatype for certain array in advance
- I tried to declare variable number of arrays as private members with preprocessor, but it seems loops and other code do not work well inside private: declaration
Any idea from anybody?
constructor that accepts variable number of arrays:
vector< vector<T> > ?
the inner vectors can be of different sizes but must be of the same type.
constructor member function with variable number of parameters
You can use a function with variable number of parameters that creates a class, look at how boost::bind works, that takes lots of different parameter lists.
boost mpl may answer what you are trying to do, although it is rather unclear.
Why not use a simple parametrized class ?
If your compiler support C++0x you can also use initializer list for constructors with variable number of paramaters.
template<class ArrayType>
class ArrayContainer
{
std::vector<ArrayType> m_arrays;
public:
ArrayContainer(std::initializer_list<ArrayType> arrays)
{
m_arrays.reserve(arrays.size());
std::copy(arrays.begin(), arrays.end(), m_array);
}
};
The constructor now accepts variable number of arrays.
auto container = new ArrayContainer({ a, b, c });
I'm in the process of creating a class that stores metadata about a particular data source. The metadata is structured in a tree, very similar to how XML is structured. The metadata values can be integer, decimal, or string values.
I'm curious if there is a good way in C++ to store variant data for a situation like this. I'd like for the variant to use standard libraries, so I'm avoiding the COM, Ole, and SQL VARIANT types that are available.
My current solution looks something like this:
enum MetaValueType
{
MetaChar,
MetaString,
MetaShort,
MetaInt,
MetaFloat,
MetaDouble
};
union MetaUnion
{
char cValue;
short sValue;
int iValue;
float fValue;
double dValue;
};
class MetaValue
{
...
private:
MetaValueType ValueType;
std::string StringValue;
MetaUnion VariantValue;
};
The MetaValue class has various Get functions for obtaining the currently stored variant value, but it ends up making every query for a value a big block of if/else if statements to figure out which value I'm looking for.
I've also explored storing the value as only a string, and performing conversions to get different variant types out, but as far as I've seen this leads to a bunch of internal string parsing and error handling which isn't pretty, opens up a big old can of precision and data loss issues with floating point values, and still doesn't eliminate the query if/else if issue stated above.
Has anybody implemented or seen something that's cleaner to use for a C++ variant data type using standard libraries?
As of C++17, there’s std::variant.
If you can’t use that yet, you might want Boost.Variant. A similar, but distinct, type for modelling polymorphism is provided by std::any (and, pre-C++17, Boost.Any).
Just as an additional pointer, you can look for “type erasure”.
While Konrad's answer (using an existing standardized solution) is certainly preferable to writing your own bug-prone version, the boost variant has some overheads, especially in copy construction and memory.
A common customized approach is the following modified Factory Pattern:
Create a Base interface for a generic object that also encapsulates the object type (either as an enum), or using 'typeid' (preferable).
Now implement the interface using a template Derived class.
Create a factory class with a templateized create function with signature:
template <typename _T> Base * Factory::create ();
This internally creates a Derived<_T> object on the heap, and retuns a dynamic cast pointer. Specialize this for each class you want implemented.
Finally, define a Variant wrapper that contains this Base * pointer and defines template get and set functions. Utility functions like getType(), isEmpty(), assignment and equality operators, etc can be appropriately implemented here.
Depending on the utility functions and the factory implementation, supported classes will need to support some basic functions like assignment or copy construction.
You can also go down to a more C-ish solution, which would have a void* the size of a double on your system, plus an enum for which type you're using. It's reasonably clean, but definitely a solution for someone who feels wholly comfortable with the raw bytes of the system.
C++17 now has std::variant which is exactly what you're looking for.
std::variant
The class template std::variant represents a type-safe union. An
instance of std::variant at any given time either holds a value of one
of its alternative types, or in the case of error - no value (this
state is hard to achieve, see valueless_by_exception).
As with unions, if a variant holds a value of some object type T, the
object representation of T is allocated directly within the object
representation of the variant itself. Variant is not allowed to
allocate additional (dynamic) memory.
Although the question had been answered for a long time, for the record I would like to mention that QVariant in the Qt libraries also does this.
Because C++ forbids unions from including types that have non-default
constructors or destructors, most interesting Qt classes cannot be
used in unions. Without QVariant, this would be a problem for
QObject::property() and for database work, etc.
A QVariant object holds a single value of a single type() at a time.
(Some type()s are multi-valued, for example a string list.) You can
find out what type, T, the variant holds, convert it to a different
type using convert(), get its value using one of the toT() functions
(e.g., toSize()) and check whether the type can be converted to a
particular type using canConvert().