I have the following code in myclass.h file:
typedef std::unordered_set< int, int> Parameters;
class MyClass
{
public:
void myFunction();
private:
Parameters* m_params;
}
Then, myFunction looks as follows:
void MyClass::myFunction()
{
...
m_params->emplace(1,1);
}
When I try to compile, I get:
term does not evaluate to a function taking 1 arguments
If I comment the emplace line, the error disappears. However, I don't find any misuse related to this function signature:
http://en.cppreference.com/w/cpp/container/unordered_map/emplace
Any help would be much appreciated.
Simple typo: You used std::unordered_set in your code, but you meant std::unordered_map.
Your implementation doesn't recognise any error setting Hash to int in the std::unordered_set template until you try to put something into the container. Then it tries to hash the input, and realises it can't use an int as a function.
Related
I have the following class with a method signature as below:
class Foo
{
public:
std::vector<std::string> barResults(const std::vector<std::string>&, const std::vector<std::string>&);
}
In the implementation file, I've got this:
std::vector<std::string> Foo::barResults(const std::vector<std::string>& list1, const std::vector<std::string>& list2)
{
std::vector<std::string> results;
// small amount of implementation here...
return results;
}
So I thought to myself, let's see if I can simplify this function signature a bit with some auto-magic as it's getting to be a "bit of a line-full"! So I tried this...
class Foo
{
public:
auto barResults(const std::vector<std::string>&, const std::vector<std::string>&);
}
auto Foo::barResults(const std::vector<std::string>& list1, const std::vector<std::string>& list2)
{
std::vector<std::string> results;
// small amount of implementation here...
return results;
}
Now ignoring the fact that, yes I can use a "using namespace std", to trim it down a lot, I was wondering why the compiler gave me an error "a function that returns 'auto' cannot be used before it is defined".
I personally would have thought the compiler would have easily been able to deduce the return type of the method, but in this case it doesn't seem so. Sure, you can fix it with a trailing return type as below:
class Foo
{
public:
std::vector<std::string> barResults(const std::vector<std::string>&, const std::vector<std::string>&) -> std::vector<std::string>;
}
But then if you use the above, it's no better than it was before. So, apart from "using namespace std", is there a nicer way to do the above, and why can't the compiler deduce the return-type in this instance? Or even, does it depend on how this method is invoked that's causing the compiler not to be able to figure out the return type.
The issue here is an issue of how include files work. Your error:
a function that returns 'auto' cannot be used before it is defined
means that in the file you are using your function, its definition (ie. implementation) not anywhere in the file before the usage. This means that the compiler compiling your code using the function can't deduce the functions return type, as that requires access to the definition (implementation). The most likely reason for this is that the function's definition (implementation) is in its own source (.cpp, .c, etc.) file, that is not included. To more fully understand this, I recommend reading this answer, and perhaps this answer as well.
To address the titular question, likely the easiest way to shorten that signature is with a typedef. More specifically, you can add the following code wherever you see appropriate, provided the scoping is appropriate (I would add it as a public member in your class):
typedef std::vector<std::string> strvec;
This allows you to re-write your method signature as the much more manageable:
strvec barreuslts(const strvec&, const strvec&)
When sticking to C++11, you can't rely on deduced return types, you need the trailing return type (C++14 allows that, though). As there is nothing special about the trailing return type in your case, i.e., no expression is passed decltype to determine the return type, I would instead try to shorten the method signature with some type aliases:
class Foo
{
public:
using StrVec = std::vector<std::string>;
StrVec barResults(const StrVec&, const StrVec&);
};
Foo::StrVec Foo::barResults(const StrVec& list1, const StrVec& list2)
{
StrVec results;
// small amount of implementation here...
return results;
}
If you are just looking for a visually appealing way to deal with longer signatures, stop forcing everything to be on one line. Be liberal with your vertical spacing and insert line breaks. The signature contains quality information for the caller and what you may be looking for is a multi-line signature. If you are working with 80 character page widths, reconsider the indentation on the access specifier.
class Foo
{
public:
std::vector<std::string> barResults(const std::vector<std::string>&,
const std::vector<std::string>&);
}
std::vector<std::string>
Foo::barResults(const std::vector<std::string>& list1,
const std::vector<std::string>& list2)
{
std::vector<std::string> results;
// small amount of implementation here...
return results;
}
There are many styles when it comes to splitting up a declaration. Having a tool like clang-format in your toolset will do this automatically and consistently for you.
I am trying to create a map for which the value is a class I have defined in another file; namely, FoodItemLookup. However, C++ is giving me the error:
template argument 1 is invalid
I find this odd, because I'm not using any templates.
I would appreciate it if someone could explain to me what I am doing wrong. I don't think I'm allowed to post all of the code, but here are the snippets in question:
The attempt at making a map:
std::map<string, FoodItemLookup> foodCatalogue;
A brief rundown of the FoodItemLookup.h file:
#ifndef FOODITEMLOOKUP
#define FOODITEMLOOKUP
#include <string>
class FoodItemLookup
{
private:
...
public:
//constructor
FoodItemLookup(std::string upc, int shelfLife, std::string name);
//copy constructor
FoodItemLookup(const FoodItemLookup &other);
//destructor
~FoodItemLookup();
...
);
#endif
You should have std:: in from of string in your first template argument:
std::map<std::string, FoodItemLookup> foodCatalogue;
"I find this odd, because I'm not using any templates."
Actually std::map uses templates. That's why you need to pass 2 types (here, std::string and FoodItemLookup) between the <> when instantiating your std::map.
More information on templates.
I'm tried to make a map to class methods using C++11's function.
The C-Style function pointers:
Method:
void MyClass::MyMethod(void*);
Map declare:
std::map<int, void (MyClass::*)(void*)> mapIdToMethod;
Map insert:
mapIdToMethod.insert(std::make_pair(2, &MyClass::MyMethod));
Method call:
MyClass mc;
(mc.*mapIdToMethod.at(1))(nullptr);
The code above is worked, But how can I convert it to use C++11's function?
What i'm tried:
Map declare:
std::map<int, function<void(void*)>> mapIdToMethod;//The map declare
Now, how can I insert and call the method on this map?
Probably not as efficient as the original but maybe easier to read:
std::map<int, std::function<void (MyClass&,void*)>> mapIdToMethod;
mapIdToMethod.emplace(2, [](MyClass& c,void* p){ c.MyMethod(p);});
// alternatively:
using std::placeholders::_1;
using std::placeholders::_2;
mapIdToMethod.emplace(2,std::bind(&MyClass::MyMethod,_1,_2));
MyClass mc;
mapIdToMethod.at(2)(mc, nullptr);
I am also a fan of function over C-style pointers, but it's important that you recognize that the analog for void (MyClass::*)(void*) is function<void(MyClass&, void*)> not function<void(void*)>. So you could replicate what you've already have going in MapIdToMethod with:
map<int, function<void(MyClass&, void*)>> bar;
You could insert to this the same way as you inserted to MapIdToMethod (bar.insert(make_pair(2, &MyClass::MyMethod)), but you could also use mem_fn, which wouldn't have been possible to use when inserting to MapIdToMethod:
bar.insert(make_pair(2, mem_fn(&MyClass::MyMethod)));
Now, to answer your question. Given:
map<int, function<void(void*)>> foo;
You can insert member functions which take a void* and don't return anything, but only if you already have the object on which you wish to make the calls constructed. You can do that using bind:
MyClass mc;
foo.insert(make_pair(2, bind(&MyClass::MyMethod, mc, placeholders::_1)));
Live Example
I got two classes: TJob and Reload_Job. Reload_Job extends from TJob:
class reload_job: public TJob
I got a function:
void run_all_threads(std::vector<TJob*> &jobs){...}
and a call:
std::vector<reload_job*> jobs;
thread_pool->run_all_threads(jobs); //error: No matching function
A got an error at that call. However, if i changed the function's form into:
void run_all_threads(TJob* job)
and the call:
reload_job* job;
thread_pool->run_all_threads(job); it work
Could you guys help me explain that why I got an compling error in the case of vector of Tjob pointer. Thanks so much!
Your issue stems from the fact that vector< reload_job* > is not a sub-type of vector< TJob* >, even though reload_job is a sub-type of TJob.
In your first example, the compiler searches for a function with the signature run_all_threads(vector < reload_job* >). There is no function with that signature.
void run_all_threads(std::vector<TJob*> &jobs){...}
std::vector<reload_job*> jobs;
thread_pool->run_all_threads(jobs); //error: No function matches run_all_threads(vector <reload_job*>)
However, in your second case, reload_job is a TJob, so the compiler matches the functions.
void run_all_threads(TJob* job)
reload_job* job;
thread_pool->run_all_threads(job); The compiler matches the function
To solve your issue, change the parameter to the function to be a vector< TJob* >. You can store the reload_jobs in a vector < TJob* >, since reload_job is a TJob.
void run_all_threads(std::vector<TJob*> &jobs){...} // function signature doesn't change
std::vector<TJob*> jobs; // this vector can store TJob and/or reload_job
thread_pool->run_all_threads(jobs); // now the types match
I've written similar kind of class skeleton where i didn't see any problem.
Will you give more details about your class implementation.
class TJob
{
public:
TJob()
{
}
};
class reload_job: public TJob
{
public:
reload_job()
{
}
void run_all_threads(std::vector &jobs)
{
}
};
int main(){
std::vector<TJob*>vec;
vec.push_back(new reload_job());
reload_job rj;
rj.run_all_threads(vec);
return 0;
}
The function takes a std::vector<TJob*> and you try to pass it a std::vector<reload_job*>. It really is that simple. These are different vectors, even though their contents are convertible.
My goal is to store all the keys of a map (first item) to a vector and I'm doing the following.
template < class vecDet>
class storeInto
{
public:
storeInto(vecDet& source) : VectorInfo(source) { }
~storeInto();
template <class pairdet>
void operator()(pairdet& pairinfo)
{
VectorInfo.push_back(pairinfo.first);
}
private:
vecDet& VectorInfo;
};
template<class mapDet, class vecDet>
void storeMapToVector(const mapDet& mapContA, vecDet& vecContA)
{
for_each(mapContA.begin(), mapContA.end() , storeInto<vecDet>(vecContA));
}
Finally, from my main program, I'm calling the storeMapToVector() as follows
storeMapToVector<mapinfo,vector<char> >(mapContents, vecContents);
where mapinfo is declared as follows
typedef map<char,int> mapinfo;
Is there a better way to do this? Is there anything wrong with this?
Your code looks like it would work at first glance. However, there's a much simpler way to do this:
I haven't evaluated your code, but there is certainly a much easier way to do what you want built into most STL implementations:
vecContents.resize(mapContents.size());
std::transform(mapContents.begin(), mapContents.end(), vecContents.begin(),
select1st<pair<const char, int> >());
Alternatively:
vecContents.resize(mapContents.size());
std::transform(mapContents.begin(), mapContents.end(), vecContents.begin(),
select1st<mapinfo::value_type>());
There is 1 wrinkle though - select1st is a SGI extension. It's in almost every STL implementation but where varies. For GNU, you have to do:
#include <ext/functional>
using __gnu_cxx::select1st; // or just using namespace __gnu_cxx;
See this answer for using it in Visual Studio.
The code seems fine. Some nitpicks though:
~storeInto();
What do you need the destructor for? The functor could just live without it.
storeMapToVector<mapinfo,vector<char> >(mapContents, vecContents);
The template argument list seems unnecessary here, it could just be
storeMapToVector(mapContents, vecContents);
The template parameters would be inferred in this context.