g++ expects an unqualified-id, but what is it expecting? - c++

I'm following a lesson on type aliases in a c++ book, and tried compiling the code below:
#include <cstdio>
#include <stdexcept>
template <typename To, typename From>
struct NarrowCaster const { //first error points here
To cast(From value) {
const auto converted = static_cast<To>(value);
const auto backwards = static_cast<From>(converted);
if(value != backwards) throw std::runtime_error{ "Narrowed!" };
return converted;
}
};
template <typename From>
using short_caster = NarrowCaster<short, From>; //second error
int main(){
try {
const short_caster<int> caster;
const auto cyclic_short = caster.cast(142857); //third error
printf("cyclic_short: %d\n", cyclic_short);
}catch(const std::runtime_error& e) {
printf("Exception: %s\n", e.what());
}
}
unfortunately, g++ (or clang++, because I'm using OS X) says this:
typealias.cpp|5 col 27 error| expected unqualified-id
which seems to also cause 2 more errors:
typealias.cpp|15 col 34 error| expected ';' after alias declaration
typealias.cpp|19 col 27 error| variable has incomplete type 'const short_caster<int>' (aka 'const NarrowCaster')
typealias.cpp|5 col 8 error| note: forward declaration of 'NarrowCaster'
I've tried fixing this issue, I'm already using std=c++17, and checked for non-ascii characters and made sure there aren't any differences from the code in the book. What am I doing wrong?
compiler command, if it helps:
g++ typealias.cpp -o typealias -std=c++17

struct NarrowCaster const {...
The const goes after a member function which means the function will not modify any data members:
To cast(From value) const {...}

Related

Compilation errors with clang when using a custom trait and a c++11 enum of type bool

The following code compiles fine with g++ and fails with clang (all versions I've tested):
#include <iostream>
namespace has_insertion_operator_impl
{
typedef char no;
typedef char yes[2];
struct any_t
{
template <typename T>
any_t(const T&);
};
yes& testStreamable(std::ostream&);
no testStreamable(no);
no operator<<(const std::ostream&, const any_t&);
template <typename T>
struct has_insertion_operator
{
static std::ostream& s;
static const T& t;
static const bool value = sizeof(testStreamable(s << t)) == sizeof(yes);
};
} // namespace has_insertion_operator_impl
template <typename T>
struct has_insertion_operator : has_insertion_operator_impl::has_insertion_operator<T>
{};
enum A : bool {
Yup = true,
Nop = false,
};
template <typename T>
bool getTraitVal(const T&) { return has_insertion_operator<T>::value; }
int main() { std::cout << getTraitVal(A::Yup) << std::endl; }
The error (with clang only!) is this:
prog.cc:24:59: error: use of overloaded operator '<<' is ambiguous (with operand types 'std::ostream' (aka 'basic_ostream<char>') and 'const A')
static const bool value = sizeof(testStreamable(s << t)) == sizeof(yes);
I believe this is a small enough example. Here are links to online compilers for it:
clang 3.8
g++ 6.1
When I change the enum type from bool to int - the error disappears.
So why is this happening? This was originally discovered when using the doctest and Catch testing frameworks - here is the bug report for Catch. Could it be a clang bug?
I know it doesn't answer your question, but it seems clang has a problem with enums of underlying type 'bool'.
I further reduced your example to:
#include <iostream>
enum A : bool {
Yup = true,
Nop = false,
};
int main() {
A t = Yup;
std::cout << t;
}
And here you can already have a feeling for what's happening:
prog.cc:10:15: error: use of overloaded operator '<<' is ambiguous (with operand types 'ostream' (aka 'basic_ostream<char>') and 'A')
std::cout << t;
~~~~~~~~~ ^ ~
/usr/local/libcxx-3.8/include/c++/v1/ostream:195:20: note: candidate function
basic_ostream& operator<<(bool __n);
^
/usr/local/libcxx-3.8/include/c++/v1/ostream:198:20: note: candidate function
basic_ostream& operator<<(int __n);
^
...

Nested Templates: "expected primary-expression before ')'"

i'm writing a Point class in c++ and use templates for this. But i have a compile error that i don't understand. I wrote a minimal example of the problem:
#include <array>
#include <vector>
#include <iostream>
template <typename T, int DIM>
class Point
{
private:
std::array<T, DIM> values;
public:
template <int ROW>
T get()
{
return values.at(ROW);
};
};
template <typename T>
class Field
{
public:
T print(std::vector<Point<T, 3> >& vec)
{
for (auto it : vec)
{
T bla = it.get<1>(); // the error line 27
}
};
};
int main(int argc,
char* argv[])
{
Point<double, 3> p;
double val = p.get<1>();
std::cout << val << std::endl;
Field<int> f;
std::vector<Point<int, 3> > vec;
f.print(vec);
return 0;
}
I compile with
g++ main2.cpp -std=c++11
and the output is
main2.cpp: In member function ‘T Field<T>::print(std::vector<Point<T, 3> >&)’:
main2.cpp:27:33: error: expected primary-expression before ‘)’ token
T bla = it.get< 1 >();
^
main2.cpp: In instantiation of ‘T Field<T>::print(std::vector<Point<T, 3> >&) [with T = int]’:
main2.cpp:41:16: required from here
main2.cpp:27:27: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’
T bla = it.get< 1 >();
Does someone know why the error occurs and how to solve it?
Thank you.
Since it.get<1>() is dependent on a template parameter, you need to tell the compiler that get is a template so that it can be parsed correctly:
T bla = it.template get<1>();
Additionally, you don't return anything from that print function, even though the declaration says it should return a T.
See this question for more detail about the template keyword in this context.
Change the line
T bla = it.get<1>(); // the error line 27
to:
T bla = it.template get<1>(); // the error line 27
You need the template keyword to access template member functions if the class they're in is itself a template class.

Error when calling an Integral template member function with g++ and clang++ [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 7 years ago.
I'm currently stuck on a compilation error, which I can't really identify...
Here's a minimal working example:
#include <iostream>
template <typename T, int R>
class a_type
{
public:
template <int N>
double segment()
{
return 42;
}
};
template <int M>
double func()
{
a_type<double, M> a;
return a.segment<1>();
}
int main(int argc, char *argv[])
{
std::cout << func<10>() << std::endl;
return 0;
}
The error message from GCC reads:
g++ main.cpp -o main
main.cpp: In function 'double func()':
main.cpp:18:26: error: expected primary-expression before ')' token
return a.segment<1>();
^
main.cpp: In instantiation of 'double func() [with int M = 10]':
main.cpp:23:28: required from here
main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
return a.segment<1>();
^
Clang also says something similar:
clang++ main.cpp -o main
main.cpp:18:26: error: expected expression
return a.segment<1>();
^
So based on GCC's error message, 'a.segment' is a member function call missing the parentheses, which obviously gets rejected. But that does not make sense at all, since I don't see any reason for treating that expression as such.
Moreover, if I change M to any integral number on line 17, like so:
#include <iostream>
template <typename T, int R>
class a_type
{
public:
template <int N>
double segment()
{
return 42;
}
};
template <int M>
double func()
{
a_type<double, 58> a;
return a.segment<1>();
}
int main(int argc, char *argv[])
{
std::cout << func<10>() << std::endl;
return 0;
}
then the code compiles and produces the expected result.
I would be very happy if somebody could enlighten me and show me what I am missing here.
The compiler doesn't know that a.segment is a template (it might depend on the value of M). So you have to tell it:
return a.template segment<1>();
In your second example it knows everything about the type of a, and so there is no problem.
The compiler tells you that it has problems with
a_type<double, M> a;
return a.segment<1>();
because it cannot tell what members a can have, as it is a template (that might be specialized for some values of M).
main.cpp:18:22: error: invalid operands of types '<unresolved overloaded function type>' and 'int' to binary 'operator<'
return a.segment<1>();
^
If segment is a template, it would be treated as segment<1>. If segment is a member variable of a, it should be compiled as a.segment < 1. How is the compiler to know?
You can fix this by using
return a.template segment<1>();

Constexpr construction and static member is not working

Consider the following code:
#include <iostream>
#include <type_traits>
template<typename Type>
class Test
{
public:
constexpr Test(const Type val) : _value(val) {}
constexpr Type get() const {return _value;}
static void test()
{
static constexpr Test<int> x(42);
std::integral_constant<int, x.get()> i;
std::cout<<i<<std::endl;
}
protected:
Type _value;
};
int main(int argc, char *argv[])
{
Test<double>::test();
return 0;
}
Under g++ 4.7.1, it returns the error:
main.cpp: In static member function ‘static void Test<Type>::test()’:
main.cpp:13:48: error: invalid use of ‘Test<Type>::get<int>’ to form a pointer-to-member-function
main.cpp:13:48: note: a qualified-id is required
main.cpp:13:48: error: could not convert template argument ‘x.Test<Type>::get<int>()’ to ‘int’
main.cpp:13:51: error: invalid type in declaration before ‘;’ token
I do not understand the problem: is it a compiler bug or is it a real problem ?
How to solve it ?
It looks like a GCC bug, clang 3.2 compiles without any error

What is causing this template-related compile error?

When I try to compile this:
#include <map>
#include <string>
template <class T>
class ZUniquePool
{
typedef std::map< int, T* > ZObjectMap;
ZObjectMap m_objects;
public:
T * Get( int id )
{
ZObjectMap::const_iterator it = m_objects.find( id );
if( it == m_objects.end() )
{
T * p = new T;
m_objects[ id ] = p;
return p;
}
return m_objects[ id ];
}
};
int main( int argc, char * args )
{
ZUniquePool< std::string > pool;
return 0;
}
I get this:
main.cpp: In member function ‘T* ZUniquePool<T>::Get(int)’:
main.cpp:12: error: expected `;' before ‘it’
main.cpp:13: error: ‘it’ was not declared in this scope
I'm using GCC 4.2.1 on Mac OS X.
It works in VS2008.
I'm wondering whether it might be a variation of this problem:
Why doesn't this C++ template code compile?
But as my error output is only partially similar, and my code works in VS2008, I am not sure.
Can anyone shed some light on what I am doing wrong?
You need typename:
typename ZObjectMap::const_iterator it = m_objects.find( id )
Since the type of ZObjectMap is dependent on the template parameter, the compiler has no clue what ZObjectMap::const_iterator is (it could be a member variable). You need to use typename to inform the compiler to assume it will be some sort of type.
Also to mention, GCC 4.5.0 gives the following output which would help you to solve the problem:
main.cpp: In member function 'T* ZUniquePool<T>::Get(int)':
main.cpp:12:7: error: need 'typename' before 'ZUniquePool<T>::ZObjectMap:: const_iterator' because 'ZUniquePool<T>::ZObjectMap' is a dependent scope
main.cpp:12:34: error: expected ';' before 'it'
main.cpp:13:11: error: 'it' was not declared in this scope
main.cpp: At global scope:
main.cpp:23:5: warning: second argument of 'int main(int, char*)' should be 'char **'