I want to have a method that takes a list as a parameter but this list should have default values, here is an invalid example for what I need:
void myFunc(std::list<CString> const & myList = std::list<CString>({"Val1", "Val2", "Val3"}));
When I try to use it I get
Error C2143: syntax error: missing ')' before '{'
Micrsoft Visual Studio 2010 does not support std::initializer_list. When you do
std::list<CString>({"Val1", "Val2", "Val3"})
You attempt to initialize the std::list using it's std::initializer_list constructor. Since MSVS 2010 doesn't support that you can call it.
One thing you can do is write a function that creates and initializes a list like
std::list<CString> default_list()
{
std::list<CString> temp;
temp.push_back("Val1");
temp.push_back("Val2");
temp.push_back("Val3");
return temp;
}
And then you can use that like
void myFunc(std::list<CString> const & myList = default_list());
Related
I would like to initalize a vector of pairs with some hard-coded values, I tried using different solutions but I keep getting compilation error. My code looks like this:
std::vector<std::pair<cv::HOGDescriptor, std::ifstream> > hogs_files = {
std::make_pair(hog, file),
std::make_pair(hog2, file2),
std::make_pair(hog3, file3),
std::make_pair(hog4, file4),
std::make_pair(hog5, file5),
std::make_pair(hog6, file6),
std::make_pair(hog7, file7),
std::make_pair(hog8, file8)
};
and the error I've got is:
Error C2440 '<function-style-cast>': cannot convert from 'initializer list' to '_Mypair'
Thank you for answers.
The error is because fstreams are not copy-constructible.
I would suggest you move your ifstreams to the vector of pairs; more clarity and control.
std::vector<std::pair<cv::HOGDescriptor, std::ifstream> > hogs_files = {
std::make_pair(hog, std::move(file)),
std::make_pair(hog2, std::move(file2)),
std::make_pair(hog3, std::move(file3)),
std::make_pair(hog4, std::move(file4)),
std::make_pair(hog5, std::move(file5)),
std::make_pair(hog6, std::move(file6)),
std::make_pair(hog7, std::move(file7)),
std::make_pair(hog8, std::move(file8))
};
The general approach to initialize the vector of pairs is OK but the problem is that std::ifstream is not copy-constructible. Hence, you won't be able to use
std::vector<std::pair<cv::HOGDescriptor, std::ifstream> > hogs_files = {
std::make_pair(hog, file),
...
};
However, you should be able to use std::ifstream* in the pair:
std::vector<std::pair<cv::HOGDescriptor, std::ifstream*> > hogs_files = {
std::make_pair(hog, &file),
...
};
This piece of code was working perfectly in VS 2013 but I had to update to VS 2015 and now it throws an error.
I did read https://msdn.microsoft.com/en-us/library/s5b150wd.aspx and googled quite a bit however I still have no idea how to fix this.
I'm using eigen math library to do some 3d math stuff. Eigen's Vector3d class cannot be used as a key to containers so I created my own Vector3dLite class to get around this issue.
class Vector3dLite
{
public:
float VertX, VertY,VertZ;
Vector3dLite(Vector3d& InputVert)
{
VertX = static_cast<float>(InputVert.x());
VertY = static_cast<float>(InputVert.y());
VertZ = static_cast<float>(InputVert.z());
}
Vector3dLite(Vector3dLite& InputVert)
{
VertX = InputVert.VertX;
VertY = InputVert.VertY;
VertZ = InputVert.VertZ;
}
//more operator overloading stuff below
}
Here's where compiler throws the error
map<Vector3dLite, int> VertexIds;
int unique_vertid = 0;
VertexIds.insert(make_pair(Vector3dLite(tri.Vert1), unique_vertid)); //This line
// Vert1 is an eigen Vector3d object
//...
Here's the compiler error:
error C2664: cannot convert argument 1 from 'std::pair<Vector3dLite,int>' to 'std::pair<const _Kty,_Ty> &&'
with
[
_Kty=Vector3dLite,
_Ty=int,
_Pr=std::less<Vector3dLite>,
_Alloc=std::allocator<std::pair<const Vector3dLite,int>>
]
and
[
_Kty=Vector3dLite,
_Ty=int
]
I did try writing const before Vector3dLite object but apparently syntax is not correct.
VertexIds.insert(make_pair(const Vector3dLite(tri.Vert1), unique_vertid));
Since the value type for a map has const object as the first element (the map key), you generally can't use make_pair to construct the value, as the inferred type will not be const.
You can create a pair with explicit types:
std::pair<const Vector3dLite, int>(Vector3dLite(tri.Vert1), unique_vertid)
You can use the map's type
std::map<Vector3dLite, int>::value_type(Vector3dLite(tri.Vert1), unique_vertid)
Or you can create a named const object to use is make_pair
const Vector3dLite mapkey(tri.Vert1);
make_pair(mapkey, unique_vertid);
One other note: Your constructors should take their parameters by const &.
The need to do this has arisen since I want run to use all the other tuple elements. Basically, I have a vector of these tuples to form a kind of table. I couldn't figure out myself how to properly do this.
Edit: Apparently the previous, simplified code gives a different error, so ignore that. This code here is how I have it in my code. (Sorry)
class GUI {
using win_t = std::tuple<sf::RenderWindow&, Container&, std::unique_ptr<std::thread>, std::condition_variable>;
enum { WINDOW, CONT, THREAD, CV }
std::vector<win_t> windows;
void run(win_t &win);
win_t &addWindow(sf::RenderWindow & window, Container & c) {
windows.emplace_back(std::forward_as_tuple(window, c, nullptr, std::condition_variable()));
win_t &entry = windows.back();
std::get<GUI::THREAD>(entry) = std::make_unique<std::thread>(&GUI::run, this, entry); // error is on this line
return entry;
}
}
And the Error I'm getting:
Error C2280 'std::tuple<sf::RenderWindow &,Container &,std::unique_ptr<std::thread,std::default_delete<_Ty>>,std::condition_variable>::tuple(const std::tuple<sf::RenderWindow &,Container &,std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::condition_variable> &)': attempting to reference a deleted function dpomodorivs c:\program files (x86)\microsoft visual studio 14.0\vc\include\tuple 75`
Take a closer look at the error you're getting, substituting out the types:
Error C2280 'std::tuple<Ts...>::tuple(const std::tuple<Ts...>&)': attempting to reference a deleted function dpomodorivs c:\program files (x86)\microsoft visual studio 14.0\vc\include\tuple 75`
You're trying to use the copy constructor on your tuple, which is noncopyable (due to the unique_ptr and condition_variable). On that line, that is happening here:
std::make_unique<std::thread>(&GUI::run, this, entry)
Or more specifically, in the underlying std::thread constructor call. entry isn't copyable, but the thread constructor copies all of its arguments internally. Even if entry were copyable, this isn't want you want anyway since run() will then be called with a reference to thread's copy and not with the specific entry you want.
For that, you need std::ref():
std::make_unique<std::thread>(&GUI::run, this, std::ref(entry))
i got some issues trying to convert my map into a set
I got a "Chanson" object with this member data :
std::map<std::string,Artiste*> m_interpretes;
Here is how i add my *Artiste to my map :
void Chanson::addArtiste(Artiste* a) throw (ExceptionArtiste, ExceptionLangueIncompatible)
{
if(a!=NULL)
{
if(a->getLangue() == this->getLangue())
{
m_interpretes.insert(pair<string, Artiste*>(a->getNom(), a));
//m_interpretes[a->getNom()] = a;
}
else
{
throw ExceptionLangueIncompatible(a,this);
}
}
}
set<Artiste*> Chanson::getArtistes() const
{
//set<Artiste*> machin;
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
}
i got this error due to this function :
Error C2664: 'std::pair<_Ty1,_Ty2> std::set<_Kty>::insert(Artiste *&&) : impossible de convertir le paramètre 1 de const std::pair<_Ty1,_Ty2> en 'Artiste *&&' c:\program files (x86)\microsoft visual studio 11.0\vc\include\set 179 1
Any idea how to fix it?
A map is an associative data structure, while a set only contains unordered collection of items, so adding a pair (key, value) is invalid for the latter and only holds for the former.
To make a set of keys from a map, you can do
std::set<Artiste*> tempSet;
std::transform(m_interpretes.cbegin(), m_interpretes.cend(),
std::inserter(tempSet, tempSet.begin()),
[](const std::pair<std::string, Artiste*>& key_value)
{ return key_value.second; });
return tempSet;
The std::set constructor you are trying to use will try to construct an element from everything the range you pass it:
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
But the element type of that range is
std::pair<const std::string, Artiste*>
which is definitely not convertible to Artiste*, which is why you are getting that error about not being able to convert. You could just do it manually though:
std::set<Artiste*> s;
for (const auto& pair : m_interpretes) {
s.insert(pair.second);
}
The problem is here:
return set<Artiste*> (m_interpretes.begin(), m_interpretes.end());
If you have a look at the types you get from the map::begin() and map::end() functions you see that you get an iterator of std::pair<string, Artiste*>.
The problem is that the set::insert() function expects the iterators it is given to be of type Artiste*.
The simplest fix would be to create the set with a for loop, as shown in Barry's answer.
I am trying to store email addresses written in a file and sort them by hits in the file.
I am storing the email addresses and the number of hits in a class called emailAddress.
I am managing the members of that class in a Deque in another class called AddressManager.
The sort function I am trying to use is the sort from the algorithm library. Like this.
[emailAddress.released() returns the number of hits. addressQueue is my emailAddress Deque]
bool AddressManager::swapTest(const emailAddress& address1, const emailAddress& address2)
{
cout<<"Comparing: "<<address1.released()<<" to "<<address2.released()<<endl;
return address1.released()>address2.released();
}
void AddressManager::sortAddresses()
{
sort(addressQueue.begin(),addressQueue.end(),
swapTest);
}
When I compile I get this error:
1>c:\workspace\addressmanager.cpp(36): error C3867: 'AddressManager::swapTest': function call missing argument list; use '&AddressManager::swapTest' to create a pointer to member
1>c:\workspace\addressmanager.cpp(36): error C2780: 'void std::sort(_RanIt,_RanIt)' : expects 2 arguments - 3 provided
1> c:\program files (x86)\microsoft visual studio 10.0\vc\include\algorithm(3639) : see declaration of 'std::sort'
Can I pass swapTest to sort, or does it need to be defined outside of AddressManager somehow?
Or could someone suggest a way to implement my own sort in AddressManager and not use the library version at all?
Thanks,
ANkh
Just define an
struct EmailSorter
{
bool EmailSorter::operator ()(const emailAddress &a, const emailAddress &b) {
return a.released()>b.released();
}
};
EmailSorter es;
std::sort( v.begin() , v.end() , es );
and pass it to std::sort
Or make swapTest a static function and do
std::sort( v.begin() , v.end() , &AddressManager::swapTest );
Either make swapTest a static function, or use a lambda:
sort(addressQueue.begin(),addressQueue.end(),
[](const emailAddress& address1, const emailAddress& address2)
{ return address1.released() > address2.released(); }
);