Once I was asked a question during the interview.
Hence I have a function void f(std::string), and I call a function as this f("int"). So that my function must create a local int x in its body. Is there a way to get the type from const char*. I know that boost::mpl::vector does solve this kind of problem. Can anyone tell me the technique?
If user-defined types are supposed to be supported, then it's not possible without an explicit mapping provided. But for just built-in types, it can be done. You could implement a parser for type definitions and combine it with function templates, constructing the type iteratively. Something like this:
template <class T>
void parseType(std::string type)
{
std::string spec = extractOneSpecifierFrom(type);
if (spec == "[]") {
parseType<T[]>(type);
} else if (spec == "*") {
parseType<T*>(type);
} else if (spec == "const") {
parseType<const T>(type);
} // ... etc.
}
My impression of this question is:
Creating a local int is done during the compile phase.
The argument s to f(std::string s) is runtime data.
So unless you are inspecting the string during runtime and selecting a block, or a predefined template, with an int, like
if ( s == "int" ){
// declare int
int i;
}
there is no reasonable way to do this.
To have object code with every possible data type available during compilation seems to me to go against the spirit of the question.
Now, with languages that has proper reflection the solution is mostly trivial. Object intObject = Class.forName(s).newInstance();
I recently thought about this too. I came up with a class member that is casted at the start of each method based on some string and if/else block.
void* data;
string cast; //set cast with some method, could also be enum.
//make methods and/or overloads with cast blocks
Related
Say for example I have a function that returns a value from a 2-dimensional array:
float get_2d_noise(const point& p)
{
return map2D[p.x][p.y];
}
The point is a class that I've defined as part of my library:
struct point
{
int x;
int y;
}
Aside from doing this:
template<typename T>
float get_2d_noise(const T& p)
{
return noisemap[p.x][p.y];
}
Is it possible to get the same effect? I.e., create get_2d_noise in such a way that anything with an x and y member will work? (preferably catching errors at compile time, rather than runtime).
You may cheat with generic lambda (c++14), so you don't use explicitly template:
auto get_2d_noise = [&](const auto& p) -> float
{
return map2D[p.x][p.y];
};
You could write a macro that takes the name of the type as parameter and then creates the desired function. Something like
CREATE_2D_NOISE_FOR(someType)
that gets expanded to
float get_2d_noise(const someType& p) {
return noisemap[p.x][p.y];
}
However, this is highly not recommended, as you loose all the expressiveness of templates and gain all the problems that come with macros.
One possibility woud be to be syntactically explicit about what youw want to do. You could create an interface IPoint or similar (which in C++ can be done using an abstract class) where you define getters for your data members, say GetX and GetY; then you could formulate your function as follows.
float get_2d_noise(const IPoint& p)
{
return noisemap[p.GetX()][p.GetY()];
}
That way, you would not have to use generics; instead, you would use inheritance. However, any type you would like to use with get_2s_noise would have to be derived from IPoint (and implement the getters in a meaningful way), but that seems to be what you are looking for.
Is it possible to get the same effect? I.e., create get_2d_noise in such a way that anything with an x and y member will work? (preferably catching errors at compile time, rather than runtime).
This is literally the entire point of the existence of templates: they were created in order to support generic programming in C++. So no, there isn't another way to write templates in C++ outside of writing templates.
I want to write a utility in my program which can convert a string to int. I know that I could use atoi or strtol for it but I need some error handling on it. Which is the better way to do it? Should I create a simple global function, maybe only in a specific namespace, or create a class that have a member which can do it for me?
For eg.:
namespace utility{
int ConvertStrToInt(std::string* str, int& convertednum)
{
//do the conversion and error handling
return convertednum;
}
}
or
class Utility{
public:
static int ConvertStrToInt(std::string* str, int& convertednum)
{//do the conversion and error handling here}
}
Sorry if the question sounds a bit silly but I am in a team with 2 other guy and we think about this very differently. 1 says the class is for everything and make classes for everything, and I think that for such a simple problem a simple function is a good solution.
So which is the more efficient? When should I use a simple function and when is the point from where class is the good solution?
Thx for everyone!
The class Utility as you have written it down above somehow contradicts the idea behind object oriented programming, as the method neither uses nor depends on any members of the class. Classes should rather be objects that have certain properties and methods on these properties.
If it is useful to have state in your conversion, use a class. Preferably, a functor so you can pass an instance around as a callable entity. If there is no state, then use a function.
As an aside, your signature and return type should probably look like this:
int ConvertStrToInt(const std::string& str);
Edit concerning this particular example, the C++ standard library provides this functionality already, so you don't need to re-implement it.
namespace is the usual way to go about this.
The function in the class should be declared static anyway, and having a class just so you can group functions together isn't good practice.
Neither. Go for a function object (sometimes called a Functor).
struct str_to_int {
int operator()(const std::string& s) const { return 23; }
};
Why? This gives you the ability to add state if you need it. It works
with all standard algorithm facilities and every modern C++
library. You can make it a template function without your users every
noticing it.
Now you can do things like:
std::vector<std::string> strings;
std::vector<int> integers;
std::transform(begin(strings), end(strings),
std::back_inserter(integers), str_to_int());
Or someday turn your definition into:
struct str_to_int {
int operator()(const std::string& s) const { return 23; }
// ha
int operator()(const std::wstring& s) const { return 42; }
// haha!
int operator()(const char* x) const { return 42; }
};
and the above code will continue to work without a problem. This wont be the case for a free function.
Random Remark: Why would you pass a pointer to a string for
something like that?
I would normally just use a function. Putting it into a class is just
noise (or pseudo-OO, since the class doesn't have any real behavior on
its own).
There is one exception: functional template arguments to the STL are
generally more efficient if you use a class with an operator()(),
rather than a function. (If you use a functional object, the actual
function being called is a compile time constant, and can easily be
inlined. If you use a function, the template argument is the type of
the function, not the function itself, and inlining is less likely.)
Even in this case, however, I'd start with the function, and add the
functional object type if needed.
I'm writing some code to translate a C++ type to an appropriate type for a SQL DB. I want to identify the type, and then depending on what it is, produce the appropriate SQL code. I'm not sure exactly what can be done in this regard by using RTTI, auto, or decltype. I have some ideas but I'm not sure if they're workable.
For instance (I know the following may not be valid C++, I'm just trying to get the idea across):
if (decltype(some_var) == int) { do_stuff(); }
or
if (decltype(some_var) == decltype(1) { do_stuff(); }
or
switch(decltype(some_var)) {
case int:
do_int_stuff();
break;
case string;
do_string_stuff();
break;
case bool;
do_bool_stuff();
break;
}
or
string get_func_y(int var) {
...
return my_string;
}
string get_func_y(string var) {
...
return my_string;
}
string get_func_y(bool var) {
...
return my_string;
}
...
string SQL = get_func_y(some_var);
Any of this look like it would work, or does anyone have advice on how to go about this? Thanks ahead of time for any input you may have.
You can use a simple metaprogramming function to determine (at compile time) whether two types are the same:
template <typename T, typename U>
struct same_type
{
static const bool value = false;
};
template <typename T>
struct same_type< T, T >
{
static const bool value = true;
};
Whether that actually helps you with your program or not is a different question. I would just go for the simple function overload solution.
Your last option of using simple function overloading should work fine.
In C++, variables and functions have static types. The only possible confusion, other than misusing casts, is whether a pointer to a base class is pointing to a base or some derived. This means that your decltypes are going to be useless as conditions (except for class derivation), since they will have a constant answer.
Overloaded functions work well with static typing. Use them.
So, I'm learning C++, and I've run into something which I know how to do in Java, but not in C++ :).
I have a template for a container object, which is defined as such:
template <class T>
class Container {
vector<T> contained;
public:
void add(T givenObject) {
this->contained.push_back(givenObject);
}
T get(string givenIdentifier) throw (exception) {
for (int i = 0; i < this->contained.size(); i++) {
if (this->contained[i].getIdentifier() == givenIdentifier) {
return this->contained[i];
}
}
throw new exception("An error has occured which has caused the object you requested to not be found. Please report this bug.");
}
bool empty() {
return this->contained.empty();
}
bool identifierExists(string givenIdentifier) {
for (int i = 0; i < this->contained.size(); i++) {
if (this->contained[i].getIdentifier() == givenIdentifier) {
return true;
}
}
return false;
}
};
This actually works very well, with one small issue. It comes down to two lines: the first is the template definition and the second is
this->contained[i].getIdentifer()
In Java, when declaring a Generic (template) one can define a superclass/interface which all members of T must extend in order to not create an error. However, I'm not sure of a way to do this in C++, and my concern is that coupling the implementation here to a getIdentifier method which might not be defined is bad design.
Now, it's not a huge deal if that's the case, this is just a little challenge project to help me learn the language, but I like to try to do things right. Is there a way to do what I'm thinking? I know you can do it with primitives, for instance:
template <int T>
is valid, but when I try to use a user defined class, I get a compiler error. Any suggestions?
It's not possible for you to put artificial limitations on template type parameters. If the type given doesn't support the way you use it, you'll receive a compiler error. A feature called 'concepts,' which would essentially allow this, was going to be added to the next C++ standard, but it was delayed to the next-next standard due to time constraints. If T doesn't have a visible getIdentifier() function, the instantiation won't compile.
Template parameters need to be deduced at compile time. template<int T> is valid because the first template parameter is an integer; you can instantiate it with any constant integer. If you attempted to use it with a non-const integer variable, it wouldn't compile. An instance of a class isn't a compile time constant, so it can't be used.
You've gotten a couple of other answers, both quite good (especially #dauphic's, IMO). I'd just add that the code you've given really looks an awful lot like quite an inefficient imitation of an std::map. Under most circumstances, std::map will probably work better. If you look up its interface, it'll also show you a way to decouple your container from having to specify getIdentifier() directly -- instead of directly using something like getIdentifier(), it uses a comparison functor that defaults to std::less<T>, which will (in turn) use T::operator< -- but you can also specify an entirely different comparison functor if you prefer.
I should also point out that while others have pointed out that you'll get a compile error if you use getIdentifier (or whatever) and attempt to instantiate over a class that doesn't supply it. I feel obliged to warn you, however, that the error message you get may be long, convoluted, and quite difficult to decipher. This is especially likely if there's some other type that does have a getIdentifier member available. In this case the error message you get say something like "Unable to to convert from type A to type B", where type A is whatever type you used to instantiate the container, and type B is whatever (often entirely unrelated) type that happens to have a getIdentifier member. What's happening is that the compiler sees that you've used getIdentifier, and sees that type B has that, so it tries to convert your type A object to a type B object, and finds that it can't, so that's what it tells you about in the error message.
P.S. Yes, I know this is really more of a comment than an answer. I apologize for that, but it won't really fit in a comment.
You don't have to do anything. If contained[i] doesn't have a getIdentifer() function, you will get a compile-time error (just as you would using an interface contrainst in Java, and just as you would outside of using templates).
To elaborate: If you were to write,
int x = 10;
long id = x.getIdentifer();
That would be considered a "bad design". It would just be a mistake, which the compiler will catch. That is exactly what will happen in you're example.
C++ draws a pretty stark line between compile-time polymorphism (ie Templates) and run-time polymporphism (ie inheritance). So what you want to do is not supported by the language.
One typical practice to do what you are doing is to provide, in addition to T, a type that can get an identifier of a given T. This decouples the two behaviors into two types and you can specify (in English) the interface that must be implemented.
template <class T, class StringIdForT>
class Container
{
...
bool identifierExists(string givenIdentifier)
{
StringIdForT idGetter;
for (int i = 0; i < this->contained.size(); i++)
{
if (idGetter.getIdentifier(this->contained[i]) == givenIdentifier)
{
return true;
}
}
return false;
}
};
You have a similar problem, StringIdForT must still define a specified method
Could you have:
template <class T>
const T &operator[] (unsigned int x)
My thinking was if you have a map<string,string> it would be nice to have a wrapper class which lets you do:
obj["IntVal"]="12";
obj["StringVal"]="Test";
int i = obj["IntVal"];
How close to this can we actually get in C++? Is it worth the pain?
You can also do
class Class {
struct Proxy {
template<typename T> T as() { ... }
template<typename T> operator T() { return as<T>(); }
private:
Proxy(...) { ... }
Proxy(Proxy const&); // noncopyable
Proxy &operator=(Proxy const&);
friend class Class;
};
public:
Proxy operator[](std::string const& s) { ... }
};
Class a;
int i = a["foo"];
int i = a["foo"].as<int>();
T will be deduced to whatever the to be initialized object is. And you are not allowed to copy the proxy. That said, i prefer an explicit as<T> function like another one proposed too.
You can't - in:
int i = obj["IntVal"];
the actual type of T can't be inferred from the context since the return type isn't part of the function signature.
Moreover, storing integer values as strings is not considered as best practices, due to memory and performance considerations ;-)
Not worth it.
Templating the return type means you'd have to explicitly specify the template parameter when you call it. Something like this, maybe I have the syntax wrong:
int i = obj.operator[]<int>("IntVal");
C++ does not deduce template parameters from what you assign the result of the call to, only from the parameters you call the function with.
So you might as well just define a normal function:
int i = obj.get<int>("IntVal");
Or in this case, either do this or implement get using this:
int i = boost:lexical_cast<int>(obj["IntVal"]);
As Amit says, you could define operator[] to return a type which can be converted either to int or to other types. Then your example code can be made to compile without the explicit lexical_cast.
Have you looked at boost variant? Is this what you're looking for?
Well, what you wrote in your sample code doesn't match the question. Right now, you only have the return type templated.
But if you wanted to do something like:
template <class T>
const T &operator[const T& x]
that's valid, though maybe not terribly useful.
A map already provides an overloaded operator[] that does most of what you want. The thing you seem to want that's missing is implicit conversion from a string that happens to contain digits to an integer. One of the fundamental characteristics of C++ is static typing, which says that shouldn't be allowed -- so it's not. It'll be happy to do that conversion if you want, but you'll have to ask for it:
int i = lexical_cast<int>(obj["IntVal"]);
Alternatively, you could create a string-like class that supported implicit conversion to int. Personally, I'd advise against that. I don't object to implicit conversions nearly as strongly as many people do, but that still strikes me as a pretty lousy idea, at least for most general use.