Error calling template method in "templated-base-class" - c++

The following code does not compile, why is that? And how can I fix this?
struct A{
template<int N> int get() { return N; }
};
template <typename X>
struct B : public X {
template<int N> int get() {
return X::get<N>();
}
};
int main(int argc, const char *argv[])
{
B<A> b;
return b.get<5>();
}
Compiler error:
test.cxx: In member function ‘int B<X>::get()’:
test.cxx:8:30: error: expected primary-expression before ‘)’ token
test.cxx: In member function ‘int B<X>::get() [with int N = 5, X = A]’:
test.cxx:15:25: instantiated from here
test.cxx:8:30: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘int’ to binary ‘operator<’

you must disambiguate it, like so:
template<int N>int get() {
return X::template get<N>();
}

Related

C++: Why can't I invoke a template member function of a template parameter type? [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 6 months ago.
I am writing a template function where one of the template parameters is a type with a member function that is itself a template function. When I invoke the template member function and explicitly specify the template parameters, it appears that the code does not compile. This is illustrated in the following minimal example:
This version will compile and run just fine:
#include <iostream>
struct ar_t
{
int data[2];
ar_t(void) {data[0] = 10; data[1] = 17;}
template <const std::size_t idx> int get(void) const {return data[idx];}
};
template <const std::size_t val> struct idx_t {};
template <const std::size_t val> int idx_ar1(const ar_t& ar, const idx_t<val>& idx)
{
return ar.get<val>();
}
int main(int argc, char** argv)
{
ar_t x;
const std::size_t index = 1;
idx_t<index> i;
idx_ar1(x,i);
return 0;
}
whereas this version will not:
#include <iostream>
struct ar_t
{
int data[2];
ar_t(void) {data[0] = 10; data[1] = 17;}
template <const std::size_t idx> int get(void) const {return data[idx];}
};
template <const std::size_t val> struct idx_t {};
template <typename arr_type, const std::size_t val> int idx_ar1(const arr_type& ar, const idx_t<val>& idx)
{
return ar.get<val>();
}
int main(int argc, char** argv)
{
ar_t x;
const std::size_t index = 1;
idx_t<index> i;
idx_ar1(x,i);
return 0;
}
Note the difference in the template parameters for idx_ar1. The error message I get with g++ 11.1 and -std=c++20 is:
main.cc: In function ‘int idx_ar1(const arr_type&, const idx_t<val>&)’:
main.cc:14:24: error: expected primary-expression before ‘)’ token
14 | return ar.get<val>();
| ^
main.cc: In instantiation of ‘int idx_ar1(const arr_type&, const idx_t<val>&) [with arr_type = ar_t; long unsigned int val = 1]’:
main.cc:22:12: required from here
main.cc:14:18: error: invalid operands of types ‘<unresolved overloaded function type>’ and ‘long unsigned int’ to binary ‘operator<’
14 | return ar.get<val>();
|
How can I get around this? I require preciesly the behaviour used in the second example. This appears to be a bug in parsing the syntax, or I don't quite have a detailed understanding of the way the member function is being declared.
Try compiling with Clang, too - sometimes it gives better errors than GCC (sometimes worse):
":14:15: error: missing 'template' keyword prior to dependent template name 'get'"

Getting error: ISO C++ forbids declaration of ‘type name’ with no type

I have a nested class definition and get errors on applying a cast to the pointer to it. The following program compiles with the error:
test.cpp: In member function ‘void* Achild<T>::test(void*)’:
test.cpp:24:31: error: ISO C++ forbids declaration of ‘type name’ with no type [-fpermissive]
ShortName::ptr = (const ShortName::Ptr*)input;
^~~~~~~~~
test.cpp:24:25: error: expected primary-expression before ‘const’
ShortName::ptr = (const ShortName::Ptr*)input;
^~~~~
test.cpp:24:25: error: expected ‘)’ before ‘const’
ShortName::ptr = (const ShortName::Ptr*)input;
~^~~~~
)
test.cpp:25:6: warning: no return statement in function returning non-void [-Wreturn-type]
}
I can't understand why i am getting errors on line 24. Any help would be appreciated!
template<typename T>
class VeryLongName
{
public:
class Ptr
{
public:
int a;
Ptr() = default;
};
const Ptr* ptr;
};
template <typename T>
class Achild: public VeryLongName<T>
{
using ShortName = VeryLongName<T>;
public:
Achild<T>() = default;
void test(void * input)
{
ShortName::ptr = (const ShortName::Ptr*)input;
}
};
int main()
{
auto *achild = new Achild<int>();
auto a = new VeryLongName<int>::Ptr();
achild->test((void*)a);
}
You are missing a typename declaration:
ShortName::ptr = (const typename ShortName::Ptr*) input;
as ShortName depends on your template type.

Generalize the argument passed to boost::bind

I am trying to write a generic struct MyCounter which uses boost::bind . What I am trying to do is to write MyCounter such a way that by changing its template argument type, I could bind to different methods. I was under the impression that if I pass something like MyThread::send as a template argument, I will be able to use it directly in bind(). Apparently I was wrong. Could you kindly help me with the alternatives? Thank you
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <vector>
#include <utility>
struct MyThread //simplified
{
void send1()
{
std::cout << "In Send1\n";
}
void send2()
{
std::cout << "In Send2\n";
}
};
struct Job //ignore me
{
Job(const unsigned int interval)
: _tChk(0)
, _tInterval(interval)
{}
void operator()(unsigned long nowSec)
{
if (nowSec > _tChk)
{
_functor();
_tChk += nowSec + _tInterval;
}
}
private:
unsigned long _tChk;
const unsigned int _tInterval;
protected:
boost::function<void()> _functor;
};
struct JobInvoker //ignore me
{
typedef boost::shared_ptr<Job> JobPtr;
JobInvoker(MyThread &myThread)
: _myThread(myThread)
{}
template<typename JOB>
void addJob(const unsigned int interval)
{
JobPtr job = boost::make_shared<JOB>(interval, _myThread);
_jobs.push_back(job);
}
void operator() (JobPtr job)
{
(*job)(_now.tv_sec);
}
void invoke(timeval now)
{
_now = now;
std::for_each(_jobs.begin(), _jobs.end(), *this);
}
timeval _now;
std::vector<JobPtr> _jobs;
MyThread &_myThread;
};
//my struggle
template<typename F>
struct MyCounter : public Job
{
MyCounter(const unsigned int interval, MyThread &myThread)
: Job(interval)
{
_functor = boost::bind(&F, &myThread); //<-- Error
}
};
int main()
{
MyThread t;
JobInvoker jobInvoker(t);
jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
timeval now;//...
jobInvoker.invoke(timeval now)
return 0;
}
UPDATE:
compiled with:
g++ boost_f.cpp -lboost_system
we get the following errors:
boost_f.cpp: In constructor ‘MyCounter<F>::MyCounter(unsigned int, MyThread&)’:
boost_f.cpp:81:34: error: expected primary-expression before ‘,’ token
_functor = boost::bind(&F, &myThread); //<-- Error
^
boost_f.cpp: In function ‘int main()’:
boost_f.cpp:89:46: error: type/value mismatch at argument 1 in template parameter list for ‘template<class F> struct MyCounter’
jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
^
boost_f.cpp:89:46: error: expected a type, got ‘MyThread::send1’
boost_f.cpp:89:51: error: no matching function for call to ‘JobInvoker::addJob(int)’
jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
^
boost_f.cpp:89:51: note: candidate is:
boost_f.cpp:52:10: note: template<class JOB> void JobInvoker::addJob(unsigned int)
void addJob(const unsigned int interval)
^
boost_f.cpp:52:10: note: template argument deduction/substitution failed:
boost_f.cpp:89:51: error: template argument 1 is invalid
jobInvoker.addJob<MyCounter<MyThread::send1> >(2); //<-- Error
^
boost_f.cpp:90:46: error: type/value mismatch at argument 1 in template parameter list for ‘template<class F> struct MyCounter’
jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
^
boost_f.cpp:90:46: error: expected a type, got ‘MyThread::send2’
boost_f.cpp:90:51: error: no matching function for call to ‘JobInvoker::addJob(int)’
jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
^
boost_f.cpp:90:51: note: candidate is:
boost_f.cpp:52:10: note: template<class JOB> void JobInvoker::addJob(unsigned int)
void addJob(const unsigned int interval)
^
boost_f.cpp:52:10: note: template argument deduction/substitution failed:
boost_f.cpp:90:51: error: template argument 1 is invalid
jobInvoker.addJob<MyCounter<MyThread::send2> >(2); //<-- Error
^
boost_f.cpp:92:29: error: expected primary-expression before ‘now’
jobInvoker.invoke(timeval now)
Like the error says, a member function isn't a type, so it can't be used for a template type parameter.
Instead, you need to use a non-type parameter:
template<void(MyThread::*F)()>
struct MyCounter : public Job
{
MyCounter(const unsigned int interval, MyThread &myThread)
: Job(interval)
{
_functor = boost::bind(F, &myThread);
}
};
Live Example
Note that I made F a pointer to a member function of MyThread instead of a typename.

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