Fix Expected Unqualified id before ';' token error - c++

Rather than compiling, my code is throwing the following error:
expected unqualified-id before ‘;’ token
template std::list<SGAction_MaxMinMax>::iterator;
I've looked at other threads on similar errors, but none seem to address my problem.
//! Overloaded equality operator
/*!< Returns true if the state and action are the same. */
bool operator==(const SGAction_MaxMinMax & lhs,
const SGAction_MaxMinMax & rhs);
//! Overloaded comparison operator.
/*!< Returns true if the lhs state is strictly less than the rhs
state, or if they are equal and the lhs action is strictly less
than the rhs action/ */
bool operator<(const SGAction_MaxMinMax & lhs,
const SGAction_MaxMinMax & rhs);
template class std::list<SGAction_MaxMinMax>;
template std::list<SGAction_MaxMinMax>::const_iterator;
template std::list<SGAction_MaxMinMax>::iterator;
The error is on the second to last, and third to last, lines of code above.

template class std::list<SGAction_MaxMinMax>;
This thing is called an explicit template instantination definition. It makes the compiler instantinate std::list<SGAction_MaxMinMax>, and it causes all methods in std::list<SGAction_MaxMinMax> to be compiled, even if they aren't used.
You can read more about this rarely used feature here: Explicit instantiation - when is it used?
template std::list<SGAction_MaxMinMax>::const_iterator;
template std::list<SGAction_MaxMinMax>::iterator;
These lines don't look like valid C++ to me.
It could be an attempt at explicit instantination as well (but class is missing).
GCC doesn't compile those even if you add class (because apparently list<T>::iterator and const_iterator are type aliases rather than classes).
Simply removing those two lines might work.

Related

How does a compiler use T::operator< in std::set when the template parameter asks for std::less<T>?

When you create a std::set, one of the template parameters is class Compare, which defaults to std::less<T>.
Now, even if you don't give a specialization of std::less<T>, defining T::operator< is good enough for C++ to "figure it out". But C++ isn't figuring anything out, a compiler is.
And the compiler is going through a series of what I'm sure are simple steps. What are those steps?
The standard library is defined such that std::less<T> will use operator< unless otherwise specialized. So if you don't provide a specialization, if the type supports < then it will work out.
From std::less<T> :
Function object for performing comparisons. Unless specialized, invokes operator< on type T.
And for std::less<T>::operator() :
Possible implementation :
constexpr bool operator()(const T &lhs, const T &rhs) const
{
return lhs < rhs;
}
Check out the compiler-defined specialization of std::less<void>.
As you can see, it simply returns the result of lhs < rhs.
As for how the compiler knows to bind std::less<void> instead of std::less<T>, that's because no specialization of std::less<T> has been explicitly written. So when you ask for it, it must be automatically generated.
So why does the compiler find std::less<void> instead of std::less<>? That's because when you pass no template parameter to std::less you get std::less<void>.

Compiler throws "ambiguous overload for operator"

I'm learning how to use std::chrono and I want to make a template class Timer easy to use (defined in timer.h). The testing program was successful and everything worked fine, until I tried to use my new Timer in a program with the definition of some template operators, which conflit with the operators used inside Timer.
Inside Timer I have to use operator- between two variables (start_time and end_time) of type std::chrono::time_point, in order to obtain the duration variable containing the elapsed time.
In another header (algebra.h) I implemented the overloading of the binary operator- to make the difference between two std::vector or two std::array, or also a user-defined container provided with operator[] and size() member function.
template<typename pointType>
pointType operator-(pointType a, const pointType & b){
for(int i = 0; i < a.size(); ++i){
a[i] = a[i] - b[i];
}
return a;
}
When I try to include both timer.h and algebra.h, the compiler throws an error saying "ambiguous overload for operator-" suggesting, as possible candidates, both the operator in algebra.h and the one implemented in <chrono>.
I don't understand why it is ambiguous, since pointType can't be deduced as std::chrono::time_point because it doesn't have operator[] and size() member function.
P.S. I tried something else to work it out, but I only got more confused testing a program which use std::valarray. When I include both <valarray> and "algebra.h", and try to make a difference between two valarrays, I expected the compiler to complain about ambiguous definition of operator-, since std::valarray already has implementation for binary operators. But this doesn't happen: it compiles using the <valarray> implementation. Why this doesn't throw an error?
It is ambiguous because the compiler only looks at the function signature to test for ambiguity, not the body of the function. In your example, this is the function signature:
template<typename pointType>
pointType operator-(pointType a, const pointType & b)
Here, the template parameter pointType could be deduced as std::chrono::time_point. However, there is already a binary minus operator declared in the chrono header for std::chrono::time_point (https://en.cppreference.com/w/cpp/chrono/time_point/operator_arith2). This is what is causing the ambiguity error.
To solve this problem, you should first consider whether you need such a generic binary minus operator. The problem you are currently experiencing will not be unique to std::chrono::time_point, but will also occur with any other header that contains a class with a member or non-member binary minus operator, where both arguments are of the same type (or could implicitly convert into the same type). Perhaps a simple set of function overloads for the types in question:
template<typename T>
std::vector<T> operator-(const std::vector<T>& a, const std::vector<T>& b);
template<typename T, size_t N>
std::array<T,N> operator-(const std::array<T,N>& a, const std::array<T,N>& b);
This would be the safest option. You could also not use operator overloading altogether, and stick to a conventional function:
template<typename T>
T pointwise_subtract(const T& a, const T& b);
If you have a c++20 compiler, you could use concepts. If you insist on using non-member operator templates, you may have to use SFINAE-based template metaprogramming, a more advanced and less readable technique:
//enable this template if the type T has a member method "size" and
// subscript operator accepting variables of type "size_t"
template<typename T, typename=std::void_t<
decltype(std::declval<T>().size()),
decltype(std::declval<T>()[std::declval<size_t>()])
>
T operator-(const T& a, const T& b);
This will remove your ambiguity error.

Overloading the equals operator with a template using Effective C++

I am porting old C++ code to an Effective C++ safe version. I read about problems with this flag, but as I don't have a choice wether to do it or not, it has to be. I came along a problem with overloading the equals operator when using a template.
I tried to move the functionality from header files to the actual cpp's, but this didn't have any effect. Removing the template worked, but as the template is needed, it just showed me where the problem is.
template <typename T1, typename T2>
MyClass& operator = ( const boost::tuple<T1,T2> & _v )
{
//Some operations
return *this;
}
Compiling this code throws the following error:
'operator=' should return a reference to *this
pointing at the exact line return *this;
MyClass does not inherit any other class. Is this a effc++ bug or is there anything I am missing?

Should operators be declared as non-member non-template friends

Consider this question, which is about the following code not compiling:
std::vector<int> a, b;
std::cout << (std::ref(a) < std::ref(b));
It doesn't compile because the vector comparison operators for vector are non-member function templates, and implicit conversions aren't allowed to be considered. However, if the operators were instead written as non-member non-template, friend functions:
template <class T, class Allocator = std::allocator<T>>
class vector {
// ...
friend bool operator<(const vector& lhs, const vector& rhs) {
// impl details
}
};
Then this version of operator< would have been found by ADL and been chosen as the best viable overload, and the original example would have compiled. Given that, is there a reason to prefer the non-member function template that we currently have, or should this be considered a defect in the standard?
Given that, is there a reason to prefer the non-member function
template that we currently have, or should this be considered a defect
in the standard?
The reason is if ADL could find out proper function or not. When such a search requires to extract the substituted template parameters from the type of given object and then substitute them many times into a templated parameter of the function template, ADL can't do this because of there are no reasons in the general case to prefer one way of template parameters binding to other. The non-member function template defined after but still in the namespace scope of that template (due to friend) excludes such an indeterminacy.

C++ gcc error on operator= function

function definition
const circularLinkedList<Tp>& operator=(const circularLinkedList<Tp>& otherList);
lines that cause the error, error message refers to line 327, which starts at nodeType....
template <class Tp>
nodeType<Tp>* circularLinkedList<Tp>&::operator=(const circularLinkedList<Tp>& otherList)
And the error messages from the gcc compiler are:
circularLinkedList.h:327: error: invalid declarator before â&â token
circularLinkedList.h:327: error: expected initializer before â&â token
I assume that I have made some sort of syntax error in in defining this method somewhere. How would I have to go about fixing it? Thanks.
Can you post a little bit more code for us? Can you explain what nodeType is?
The following looks like a function definition:
template <class Tp>
nodeType<Tp>* circularLinkedList<Tp>&::operator=(const circularLinkedList<Tp>& otherList)
However, for one thing, the declaration says it returns a const circularLinkedList<Tp>&.
Also, you don't want to have the & before the ::. It needs to be the type's name, not a pointer or reference to a variable of that type. If you want that behavior you need to use a proxy class.
So it should be something like:
template <class Tp>
const circularLinkedList<Tp>& circularLinkedList<Tp>::operator=(const circularLinkedList<Tp>& other)
Which should almost invariably end with return *this;
In the first code block, you show the method declaration, not the function definition.
In the second code block, you show the header of the method definition.
Method Declaration:
Returns const circularLinkedList<Tp>&
Method Definition:
Returns nodeType<Tp>*.
You are not defining the method you declared.
You are defining some method you have not declared.
The header of the definition should be:
const circularLinkedList<Tp>& circularLinkedList<Tp>::operator=(const circularLinkedList<Tp>& otherList)