C++ gcc error on operator= function - c++

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)

Related

Why does removing 'const' from the constructor parameter stop the class from being instantiated?

Removing const from line 12 prevents the class What from being instantiated during compilation. I do not expect What to ever be instantiated, regardless of constness in the declaration. This is consistent between clang, gcc and MSVC so I assume it is standard. Marking the constructor explicit also does not prevent the instantiation. What am I not understanding here? Why does constness make a difference?
template <typename T> constexpr bool just_false() { return false; }
template<typename T>
class What {
static_assert(just_false<T>(), "Why was this class instantiated?");
};
struct The {};
struct Heck {
Heck(The) {}
Heck(const What<int>&); // Removing 'const' from this line stops 'What<int>' from being instantiated
};
int main() {
The the;
Heck{the};
}
The just_false incantation is just to prevent the static assert from always triggering regardless of instantiation.
Compiler explorer link: https://godbolt.org/z/8cETcfss5
If const is there, and What<int> happens to have a constructor taking The, that would allow Heck(const What<int> &) to be used (because a const reference can bind to a temporary produced by such constructor). Checking for that constructor of What<int> requires instantiating the What<int> template.
If there is no const, no implementation of What<int> could possibly make Heck(What<int> &); be called, so there's no point in instantiating it.
But it seems that no matter what constructor What<int> has, the Heck(The) overload would take precedence, so strictly speaking, this instantiation seems to be unnecessary in this specific case.
If What had a constructor such as What::What(The), then the implicit conversion Heck(What(the)) would be valid for Heck::Heck(const What&) but not for Heck::Heck(What&).
During overload resolution for the call Heck(the), the search for viable functions eliminates Heck::Heck(What&) but does not eliminate Heck::Heck(const What&), which gets carried over to the search for a best viable function, which requires instantiating What.
Will this stop the error message?
struct Heck {
Heck(The const&) {}; // Removing 'const' from this line causes 'What<int>' to be instantiated
Heck(const What<int>&);
};
This is supposed to prevent implicit conversion/copy constructor call.

Fix Expected Unqualified id before ';' token error

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.

Compiler mistakes template argument list for < comparison

I have a template function in the style:
template <int Exponent> DERIVED_TYPE pow(TYPE const x);
This function is defined inline in a template struct as a friend function:
template <ARGUMENTS>
struct unit {
typedef unit<ARGUMENTS> type;
....
template <int Exponent>
friend constexpr unit_pow_t<type, Exponent> pow(type const x) { ... }
};
This is because taking a value with a unit to a power has to change the unit along with the value.
When I try to use it omitting the Exponent, I can see the candidates the compiler considers for matching:
src/model/Tool.cpp:113:3: error: no matching function for call to 'pow'
pow(1._m);
^~~
src/model/../units/Units.hpp:2266:46: note: candidate template ignored: couldn't infer template argument 'Exponent'
friend constexpr unit_pow_t<type, Exponent> pow(type const x) {
^
/usr/include/math.h:255:8: note: candidate function not viable: requires 2 arguments, but 1 was provided
double pow(double, double);
^
So far things are as expected, the template is seen, but of course the Exponent needs to be specified. When I do however something unexpected happens:
src/model/Tool.cpp:113:6: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
pow<3>(1._m);
~~~^~
The compiler sees pow as the address of "double pow(double, double)" and interprets <3 as the intent to compare the function pointer with the integer. The problem occurs with clang 3.4, 3.6 and GCC 5.2.
My question is, how do I convince the compiler that <3> is a template argument list?
UPDATE
I finally managed to create a minimal example, sorry for the incomplete question:
template <int Exp>
struct metre {
double value;
template <int Exponent>
friend constexpr metre<Exp * Exponent> pow(metre<Exp> const x) {
return {0};
}
};
int main() {
pow<2>(metre<1>{1});
return 0;
};
It seems it is not seeing pow:
targs.cpp:11:2: error: use of undeclared identifier 'pow'
pow<2>(metre<1>{1});
^
If I include cmath I have the same diagnostics as before:
targs.cpp:13:5: error: comparison between pointer and integer ('double (*)(double, double)' and 'int')
pow<2>(metre<1>{1});
~~~^~
1 error generated.
So the presence of "double pow(double, double)" just masks the issue that the template is not seen. The question then is, why is pow<>() not seen by the compiler?
There is no need (and no logic) for the friend template. Use a free function:
template <int Exp>
struct metre {
double value;
};
template<int B, int A>
constexpr auto pow(metre<A> const x) -> metre<A*B>
{
return metre<A*B>{x.value};
}
int main() {
metre<2> result = pow<2>(metre<1>{1});
return 0;
};
Live demo on coliru.
This is the template friends problem, with two quirks: the name of the function being pow; and the template friend has its own template parameter!
As a rule of thumb, be on guard whenever you use friend inside a class template.
To get the easier problem out of the way first: as posted, in the MCVE, the class definition of metre doesn't cause a name pow to be declared (this will be explained later). Your error message is coming because there is in fact a visible declaration of a name pow: it's in the C standard library header math.h. The "pointer" in the error message is a function pointer to this function.
It's a good idea to not name your function the same as a function in the C standard library. Those may be defined as preprocessor macros anyway, causing further trouble.
For the rest of this post I will assume the MCVE has pow swapped out for pok , to avoid this wrinkle. Then a sane error message is generated:
po.cc:13:5: error: 'pok' was not declared in this scope
pok<2>(metre<1>{1});
^
Moving onto the main issue now.
The basic version of the problem is discussed here. The issue is that declaring a friend function inside a class template does NOT make the friend function also be a template function with the same parameter as the class template.
In fact, what happens is that for each instantiation of the class template, the friend declaration declares a non-template friend for that instantiation.
To see this in action, in your MCVE, add the line metre<1> m; as the first line of main. This instantiates metre<1>, which causes template<int Exponent> pok(metre<1>) to exist, and so the compiler recognizes pok on the next line!
In fact, any particular instantiation works, not just metre<1>, because this at least allows name lookup of pok to succeed, and then by the time overload resolution occurs (two-phase lookup!) , the argument metre<1> has caused metre<1> to be instantiated.
Closing note: I'm not entirely sure the above explanation is correct - template friends are pretty complicated. Maybe it'll turn out that actually pok is supposed to be declared and the compiler is bugged. But I concur with rubenvb's suggestion that it is best to avoid this situation entirely by not using a friend.
With the help of the previous answers I figured out a workaround.
The problem is that the friends are defined (more or less as expected) but not known outside of class/struct scope. So the compiler does not find them.
The solution is to put a declaration outside of the struct:
template <int Exp>
struct metre {
double value;
template <int Exponent>
friend constexpr metre<Exp * Exponent> pow(metre<Exp> const x) {
return {23};
}
};
template <class> void pow(); // <== HERE BE DRAGONS
int main() {
static_assert(pow<2>(metre<1>{1}).value == 23, "foobar");
return 0;
};
Note that it is not necessary to provide a matching declaration. Any template declaration for a function with the right name seems to allow the compiler to discover the friend template function.

passing function as parameter to template method of template class

The following code looks legitimate but doesn't compile
void f() {}
template<bool>
struct call_any
{
template<typename F>
static void call(F f) {}
};
template<bool B>
void call_f()
{
call_any<true>::call<void (&)()>(f); // OK
call_any<false>::call<void (&)()>(f); // OK
call_any<B>::call<void()>(f); // OK
call_any<B>::call<void (&)()>(f); // expected primary-expression before '>'
}
Why there is an error and what does it mean?
When you are dealing with types that are dependent on the template parameters within a template, the compiler doesn't know what kinds of things the members of that type are. Unless you specify otherwise, it assumes that the members are not types and not templates. Because of this, it is trying to treat < as a less-than operator, but it becomes impossible to parse the expression that way by the time it reaches the >.
To get rid of the error you should use this instead:
call_any<B>::template call<void (&)()>(f);
This tells the compiler explicitly that call is a template, so it should treat the < as the beginning of the template parameters and not a regular less-than operator.
This should use template as well:
call_any<B>::call<void()>(f);
The only reason you don't see the error on this line is that there is a way to parse it as a non-template:
(call_any<B>::call < void() ) > (f);
Although odd, it is syntatically valid, so the compiler gets past that line, and the first error you see is the one you mention. However, without the template keyword, you would eventually get an error once call_f was actually instantiated (probably -- there are weird ways it could work).
The first two examples are okay without using the template keyword. Since the type isn't dependent on the template parameters, it can be determined that call is a template while call_f is being parsed.
You might ask: "Why can't the compiler figure out it is a template? I've defined it as a template in the code right above!". The issue is specialization. You could specialize the template and do something completely different than what the primary template specifies:
template<>
struct call_any<false>
{
static const int call = 5;
};
This specialization could occur even after call_f is defined, so the compiler can't rely on what the primary template for call_any says when it is parsing call_f.

Normal function not overwriting template function

I have to use an external library, but am getting a "multiple definition error" from following template function and its explicit specialization, if it gets called with a std::string.
template <typename T>
void foo(T& value);
template <>
void foo(std::string& value);
even if I change the 2nd function to
void foo(std::string& value);
the problem is the same.
According to [1] at least the version without a template (the "plain old function") should be prefered over the template version.
Does anybody have a clue, where the problem could be?
[1] http://www.gotw.ca/publications/mill17.htm
You're breaking the one-definition rule.
Unless a function is inline, it can only be defined once. If you mark the function as inline, so long as the definitions match they can be defined as often as desired. Template functions behave as if they were implicitly inline, so you don't get errors with templates.
However, an explicit specialization or non-template function is not implicitly inline and because you're including it in multiple translation units, you get multiple definitions; this breaks the rule. You should mark it as inline:
template <>
inline void foo(std::string& value);
(If you're getting this before link time, you need include guards.)