If all of the objects you would be returning are derived from a common base class, you could use a std::map<std::string,BaseClass *>. The comparisons ultimately in there somewhere, but it keeps things better organized.
If all of the objects you would be returning are derived from a common base class, you could use a std::map<std::string,BaseClass *>. The comparisons ultimately in there somewhere, but it keeps things better organized.
No, you can't do it with standard C++. C++ has no notion of reflection. Sorry :)
1) How do I convert std::string to a C-style string?
Simply call string.c_str() to get a char const*. If you need a mutable _C-style_ string then make a copy. The returned C string will be valid as long as you don't call any non-const function of string.
2) Is there a way to get a C-style string from a stringstream?
There is, simply strstream.str().c_str(). The returned C string will be valid only until the end of the expression that contains it, that means that is valid to use it as a function argument but not to be stored in a variable for later access.
3) Is there a way to use a C-style string directly (without using stringstreams) to construct a string with an integer variable in it?
There is the C way, using sprintf and the like.
You got halfway there. You need foo.str().c_str();
your_string.c-str()-- but this doesn't really convert, it just gives you a pointer to a buffer that (temporarily) holds the same content as the string.- Yes, above,
foo.str().c_str(). - Yes, but you're generally better off avoiding such things. You'd basically be in the "real programmers can write C in any language" trap.
C++ experts - implicit conversion of String to C-string?
Converting String to Cstring in C++ - Stack Overflow
c++ - How to convert a string to a class name - Stack Overflow
c++ - Converting class to string - Stack Overflow
C++ doesn't have any introspection so no it's not possible.
However, you can "hack" it by having another std::map that contains the names as keys, and the value is a reference to the variable:
agnt temp;
std::unordered_map<char, int&> variable_map = {
{ 'x', temp.x },
{ 'y', temp.y }
};
variable_map['x'] = 123;
std::cout << variable_map['y'] << '\n';
It's generally not worth it though, as it more work. Especially if you want to do this for multiple variables (as each structure variable needs its own mapping).
You can't do this in C++ because it's a statically-typed language. One way to get this sort of behaviour is to provide accessing wrappers:
template <char c>
struct getter {
};
template <>
struct getter<'x'> {
static int get(const agnt &theAgnt) {
return theAgnt.x;
}
};
template <>
struct getter<'y'> {
static int get(const agnt &theAgnt) {
return theAgnt.y;
}
};
template <char c>
int get(const agnt &theAgnt) {
return getter<c>::get(theAgnt);
}
And call like:
agnt temp;
//... set members
std::cout << get<'x'>(temp) << std::endl;
However, the for loop won't work the way you expect, because the template parameters need to be determined at compile time. Also, you can't just request any old thing, unless you define a get function in the unspecialised getter which returns some sort of NULL-indicator, like INT_MIN.
However, this is all really a hack to get something vaguely similar to a dynamic language. But it's not really anything different from just referencing temp.x. Instead, you should try to adhere to C++ conventions and enjoy the static typing!
.c_str() returns a const char*. If you need a mutable version, you will need to produce a copy yourself.
vector<char> toVector( const std::string& s ) {
vector<char> v(s.size()+1);
std::memcpy( &v.front(), s.c_str(), s.size() + 1 );
return v;
}
vector<char> v = toVector("apple");
// what you were looking for (mutable)
char* c = v.data();
.c_str() works for immutable. The vector will manage the memory for you.
You can create a simple factory and register the classes you want to be able to construct. This is a very light-weight sort-of reflection.
#include <map>
#include <string>
template <class T> void* constructor() { return (void*)new T(); }
struct factory
{
typedef void*(*constructor_t)();
typedef std::map<std::string, constructor_t> map_type;
map_type m_classes;
template <class T>
void register_class(std::string const& n)
{ m_classes.insert(std::make_pair(n, &constructor<T>)); }
void* construct(std::string const& n)
{
map_type::iterator i = m_classes.find(n);
if (i == m_classes.end()) return 0; // or throw or whatever you want
return i->second();
}
};
factory g_factory;
#define REGISTER_CLASS(n) g_factory.register_class<n>(#n)
int main()
{
using namespace std;
REGISTER_CLASS(string);
std::string* s = (std::string*)g_factory.construct("string");
printf("s = '%s'\n", s->c_str());
*s = "foobar";
printf("s = '%s'\n", s->c_str());
return 0;
}
What you want is called virtual constructor (pattern). The availability of this feature in a language is not necessarily coupled to the language being interpreted or managed by a VM - it depends on how (and if at all) the information about types existing in a program (or library) is available at run time. This is not the case in "naked" C++ - but it can be implemented, as shown by Arvid, for example. The problem is that there is no standardized implementation of this feature, so everybody keeps re-inventing this again and again. To certain extent COM or it's platform independent counterpart XPCOM "standardize" this at component level.
Two things: first, you cannot add to an existing class without
modifying the class definition. If you have a class that you
want convertible to std::string (or to double or whatever),
you should define a conversion operator: in your case:
class Employee
{
// ...
operator std::string() const
{
return name; // Or whatever...
}
};
Second, the solution in your case isn't to provide an implicit
conversion, it is to use std::find_if with an appropriate
matcher. In C++11, this may be done by using a lambda, but in
general (and in older versions of C++), you can always define
a functional type. For cases like this, where a class has an
natural "key", I would probably add a few member classes, along
the lines of:
class Match : std::unary_function<Employee, bool>
{
std::string myName;
public:
explicit Match( std::string const& name )
: myName( name )
{
}
bool operator()( Employee const& toBeMatched ) const
{
return toBeMatched.name == myName;
}
};
Additional functional types defining an ordering relationship, or equality of keys, might be in order as well.
There is no class string, there is a class template std::basic_string.
You should never modify anything in the std namespace.
For the purpose of conversion of a type to string you can add
Employee::operator std::string()
or define a
std::ostream& operator<<( const Employee& em, std::ostream& os ); - this way your type will work with lexical_cast.
.. but what you actually need here is std::find_if().
I am storing a class object into a string using toString() method. Now, I want to convert the string into that class object.
Your question is ambiguous. It could mean at least two different things, one of which is ... well ... a serious misconception on your part.
If you did this:
SomeClass object = ...
String s = object.toString();
then the answer is that there is no simple way to turn s back into an instance of SomeClass. You couldn't do it even if the toString() method gave you one of those funky "SomeClass@xxxxxxxx" strings. (That string does not encode the state of the object, or even a reference to the object. The xxxxxxxx part is the object's identity hashcode. It is not unique, and cannot be magically turned back into a reference to the object.)
The only way you could turn the output of toString back into an object would be to:
- code the
SomeClass.toString()method so that included all relevant state for the object in the String it produced, and - code a constructor or factory method that explicitly parsed a String in the format produced by the
toString()method.
This is probably a bad approach. Certainly, it is a lot of work to do this for non-trivial classes.
If you did something like this:
SomeClass object = ...
Class c = object.getClass();
String cn = c.toString();
then you could get the same Class object back (i.e. the one that is in c) as follows:
Class c2 = Class.forName(cn);
This gives you the Class but there is no magic way to reconstruct the original instance using it. (Obviously, the name of the class does not contain the state of the object.)
If you are looking for a way to serialize / deserialize an arbitrary object without going to the effort of coding the unparse / parse methods yourself, then you shouldn't be using toString() method at all. Here are some alternatives that you can use:
- The Java Object Serialization APIs as described in the links in @Nishant's answer.
- JSON serialization as described in @fatnjazzy's answer.
- An XML serialization library like XStream.
- An ORM mapping.
Each of these approaches has advantages and disadvantages ... which I won't go into here.
Much easier way of doing it: you will need com.google.gson.Gson for converting the object to json string for streaming
to convert object to json string for streaming use below code
Gson gson = new Gson();
String jsonString = gson.toJson(MyObject);
To convert back the json string to object use below code:
Gson gson = new Gson();
MyObject = gson.fromJson(decodedString , MyObjectClass.class);
Much easier way to convert object for streaming and read on the other side. Hope this helps. - Vishesh
You can get a C++ std::string from the stream's str() function, and an immutable C-style zero-terminated string from the string's c_str() function:
std::string cpp_string = str.str();
char const * c_string = cpp_string.c_str();
You might be tempted to combine these into a single expression, str.str().c_str(), but that would be wrong; the C++ string will be destroyed before you can do anything with the pointer.
What you are doing will work, as long as you're sure that the buffer is large enough; but using the C++ string removes the danger of overflowing the buffer. In general, it's best to avoid C-style strings unless you need to use an API that requires them (or, in extreme circumstances, as an optimisation to avoid memory allocation). std::string is usually safer and easier to work with.
Unless you have a specific reason that you need an array of char instead of a standard string, I'd use the latter. Although it's not strictly necessary in this case, I'd also normally use a Boost lexical_cast instead of explicitly moving things through a stringstream to do the conversion:
std::string zipString = lexical_cast<std::string>(zip);
Then, if you really need the result as a c-style string, you can use zipString.c_str() to get that (though it's still different in one way -- you can't modify what that returns).
In this specific case it doesn't gain you a lot, but consistent use for conversions on this general order adds up, and if you're going to do that, you might as well use it here too.
Class<?> classType = Class.forName(className);
Make sure className is fully qualified class name like com.package.class Also, please share your error message that you see.
If the fully-qualified name of a class is available, it is possible to get the corresponding Class using the static method Class.forName().
Eg:
Class c = Class.forName("com.duke.MyLocaleServiceProvider");
Note: Make sure the parameter you provide for the function is fully qualified class name like com.package.class
Check here for any reference.
EDIT:
You could also try using loadClass() method.
Eg:
ClassLoader cl;
Class c = cl.loadClass(name);
It is invoked by the Java virtual machine to resolve class references.
Syntax:
public Class<?> loadClass(String name)
throws ClassNotFoundException
For details on ClassLoader check here
Here is an implementation of ClassLoader.
If you don't wish to modify the source project that RemoteFileDP lives in (or can't) you could write an extension method such as below:
public static RemoteFileDP ConvertToRemoteFileDP(this string location)
{
// Somehow create a RemoteFileDP object with your
// location string and return it
}
That way you could run the line of code you want:
RemoteFileDP remoteFile = locationDirectory;
With a slight modification as follows:
RemoteFileDP remoteFile = locationDirectory.ConvertToRemoteFileDP();
Would this allow you to solve your problem?
Although I like the idea of a constructor accepting a string more, you could define an implicit or explicit conversion operator between RemoteFileDP and string:
class RemoteFileDP
{
....
public static implicit operator RemoteFileDP(string locationDictionary)
{
//return a new and appropiately initialized RemoteFileDP object.
//you could mix this solution with Anna's the following way:
return new RemoteFileDP(locationDictionary);
}
}
This way you could actually write:
RemoteFileDP remoteFile = locationDirectory;
or, if the conversion operator were to be explicit:
RemoteFileDP remoteFile = (RemoteFileDP)locationDirectory;
Still I insist, Anna Lear's solution is better as implicit or explicit conversion doesn't really seem to be the best fit for this kind of case. For instance, if the conversion can fail due to an invalid locationDictionary value then I wouldn't recommend this path. If the conversion is always succesful no matter what value locationDictionary is (barring null) then it could be a valid solution to your problem.
I'm just putting it on the table as I think you might find it useful to know about explicit and implicit conversions in C#, in case you didn't already.