Skip to main content
gamedev.net
🔒 Locked 🎮 Unity

C++ Template Issues

Started by chaospilot 6 replies 1.3k views
Original Post
chaospilot
chaospilot
I'm having template issues. I have a Profile class which stores ordered pairs of double (time) and T (Matrix/double/int/bool/Quaternion/etc). I have a host of other functions that are working, but the following two (and slight variations on these two) arent working. I get a "error C2660: 'std::list<_Ty>::sort' : function does not take 1 arguments" when I try and call the function pmin, and the same with merge when I try to call it. HOWEVER, I don't get any errors when I dont try and call the functions. What gives? Code as follows. template class Profile { private: list> data; public: friend const T pmin(const Profile& profIn) { Profile temp = profIn; temp.data.sort(profValLesser); return temp.data.front().second; } friend const Profile mergeProfiles(const Profile& prof1, const Profile& prof2) { Profile newProf; newProf.data.merge(prof1.data, profTimeLesser); newProf.data.merge(prof2.data, profTimeLesser); return newProf; } }
chaospilot
chaospilot
Right, forgot to throw these down:

/* used to sort Profiles pairs by time */
template bool profTimeLesser(pair elem1, pair elem2) {
return elem1.first < elem2.first; }

/* used to sort Profiles pairs by value */
template bool profValLesser(pair elem1, pair elem2) {
return elem1.second < elem2.second; }
Crypter
Crypter
list<pair<double, T>> data;

Put a space between the two '>'s:
list<pair <double, T> > data;

C++ interprates >> as a right bit-shift operator,
reguardless of its synthax use.
chaospilot
chaospilot
Fixed that and it still doesnt work... I've actually done this everywhere and it works okay on MSVS 2005.To clarify I have the following things tested and they work fine:

void addData(const pair& pairIn) {
data.push_back(pairIn);}

void addData(const double tIn, const T& valIn) {
data.push_back(make_pair(tIn, valIn));}

const T getLastValue(void) {
_ASSERTE(data.size()>0);
if(data.size()>0)
return data.back().second;
else return data.front().second;}

const size_t size(void) {
return size(data); }

const pair operator()(const size_t i) {
_ASSERTE(i<=data.size() && i>=1);
if(i<=data.size() && i>=1)
{
size_t add;
list>::iterator lIt = data.begin();
for(add=1; addlIt++;
return *lIt;
}
else
return make_pair(0,0);}

const Profile operator=(const Profile& other) {
this->data = other.data;
return *this;}

friend const Profile operator-(Profile &A) {
list>::iterator lIt = A.data.begin();
for(lIt; lIt != A.data.end(); lIt++)
(*lIt).second = -(*lIt).second;
return A;}

friend const Profile operator-(const Profile &A, const Profile &B) {
return (A + (-B));}


friend const bool operator==(const Profile &A, const Profile &B) {
list>::const_iterator aIt = A.data.begin();
list>::const_iterator bIt = B.data.begin();
for(aIt; aIt != A.data.end(); aIt++) {
if(*aIt != *bIt)
return false;
bIt++;
}
return true;}
Crypter
Crypter
Besides the missing semicolen at the end of your class ( I assume its
a typo in the post) your code compilies fine for me. (MSVC++ 2005)
Deyja
Deyja
First, Crypter is right about the >>s. The compiler should interpret this as operator>>. However, MSVC++ 8.0 has an option that changes this behavior, and you obviously have it turned on, else that code wouldn't compile at all.

Second, you only get the error when actually calling the function because template functions are not compiled if they aren't actually called.

Finally, I believe the actual error within pmin function is that the compiler is unable to resolve the type of the argument you give it, gives up, and selects the non-template overload instead. Try explicitly specifying the template argument, such that the call becomes "temp.data.sort(profValLesser);". profValLesser is a template; profValLesser is a predicate. (Change the other function that does not work in the same way.)
Zahlman
Zahlman
Just a quick comment on style:

Quote:
Original post by chaospilot
friend const T pmin(const Profile<typename T>& profIn) {Profile<T> temp = profIn;temp.data.sort(profValLesser);return temp.data.front().second; }


IF you are goint to make a copy *anyway*, it is simpler to just pass by value and use the implicit copy:

// Oh, and we don't need 'typename' inside the template brackets here.friend const T pmin(Profile<T> temp) {  temp.data.sort(profValLesser);  return temp.data.front().second; }


BUT, we can in fact do much better, because there's no need to sort the whole list if we just need the smallest element:

friend const T pmin(const Profile<T>& profIn) {  return std::min_element(profIn.data.begin(), profIn.data.end())->second;}


And for that matter, why not just make it a member function? (With appropriate const correctness, of course.)

const T pmin() const {  return std::min_element(data.begin(), data.end())->second;}


As for mergeProfiles, I think we could do that at least as easily with a constructor:

// The first set doesn't have to "merge", because there are no elements in yet// for it to merge with. So we just copy them implicitly, via the initialization// list...Profile(const Profile<T>& a, const Profile<T>& b) : data(a.data) {  data.merge(b.data, profTimeLesser);}
chaospilot
chaospilot
Awesome. Worked great, with some minor modifications. I really appreciate the style advice. It's almost as valuable as the content itself because I'm an Aerospace Engineer learning C++ and my advisor doesn't catch style issues in my thesis code.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.