Template deduction [duplicate] - c++

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 8 years ago.
I have this strange (for me) behavior which I'm not able to explain and I wish to have your comments on this, please have a look at the following code:
void detach(callback_function_ptr const& ptr) {
observers.erase(remove_if(
observers.begin(),
observers.end(),
[&ptr](callback_function_ptr const& ptr2) {
return ptr.target<void(worker*)>() == ptr2.target<void(worker*)>();
}
));
}
When calling 'target' I need to specify which on I want to use, otherwise I get this compilation error:
test.cpp:47:44: error: no matching function for call to 'std::function<void(worker*)>::target() const'
And this is somehow understandable to me, I thought I may avoid to specify each time which 'target' function I want by preparing such a small 'helper':
template<typename T>
worker_ptr get_target(const function<T>& callback) {
return callback.target<T>();
}
Which looks a reasonable solution (to me :) ), but doesnt work:
test.cpp: In member function 'void (worker::* worker::get_target(const std::func
tion<T>&))(worker*)':
test.cpp:18:27: error: expected primary-expression before '>' token
return callback.target<T>();
^
test.cpp:18:29: error: expected primary-expression before ')' token
return callback.target<T>();
^
Well, here I don't catch the problem, why is not valid? Even if I use void(worker*) instead of T a compilation error is still present:
test.cpp:18:26: error: expected primary-expression before 'void'
return callback.target<void(worker*)>();
^
test.cpp:18:26: error: expected ';' before 'void'
test.cpp:18:26: error: expected primary-expression before 'void'
test.cpp:18:26: error: expected ';' before 'void'
I had used void(worker*) before in the 'detach' function with no problems, why here is not working? How does exactly behave the template type deduction and function call resolution in this case?
Thanks for your help

It should be (with extra template):
template<typename T>
worker_ptr get_target(const function<T>& callback)
{
return callback.template target<T>();
}

Related

std::function::target with template parameter pack gives "error: expected primary-expression" [duplicate]

This question already has answers here:
Where and why do I have to put the "template" and "typename" keywords?
(8 answers)
Closed 2 years ago.
When I attempt to call the method target on a std::function object using a template parameter pack, the compiler throws an error, but it works fine if the template parameters are specified explicitly in a proxy variable.
Example, modified from cppreference.com:
#include <functional>
#include <iostream>
int f(int, int) { return 1; }
int g(int, int) { return 2; }
template <typename... Args>
void test(std::function<int(Args...)> const& arg)
{
auto && ptr = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
if (ptr && *ptr == f)
std::cout << "it is the function f\n";
if (ptr && *ptr == g)
std::cout << "it is the function g\n";
}
int test()
{
test<int, int>(std::function<int(int, int)>(f));
test<int, int>(std::function<int(int, int)>(g));
}
I've tried various other ways to call target including the following:
int (*const* ptr)(Args...) = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
int (*const* ptr)(int, int) = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
int (*const* ptr)(int, int) = arg.target<int(*)(int, int)>(); // error: expected primary-expression before 'int'
const std::function<int(Args...)>& func = arg;
auto && ptr = arg.target<int(*)(Args...)>(); // error: expected primary-expression before 'int'
The compiler only appeared to be satisfied when using a proxy variable as seen here:
const std::function<int(int, int)>& func = arg;
auto && ptr = func.target<int(*)(Args...)>(); // OK, but requires specifying the template arguments for func
As can be seen, this workaround deviates from the previous non-working example only by explicitly specifying the function parameters instead of relying on the parameter pack. (I could bypass the proxy variable with a static_cast e.g. static_cast<std::function<int(int,int)>&>(arg).target<int(*)(Args...)>(), but this also requires knowing the parameters for the cast.) If I already knew what parameters were going to be used then I wouldn't be using a variadic template since it wouldn't be necessary. But since I don't, how can I fix this? Am I doing something wrong, is this a compiler bug, or what exactly is going on here?
Note:
For reference, I'm compiling with GCC version 6.3.0 with MinGW on Windows 10.
arg.template target<int(*)(Args...)>(
You need to disambiguate when the std function type is dependent on template args.
C++ doesn't know arg.target is a template when parsing your template function prior to the function being called. And it has to parse it before it is called; this isn't a macro.
So whenever you name a type in a context dependent on your template arguments, or instantiate a template in a context dependent on your template args, you have to tell the parser.

rapidjson error: expected unqualified-id before 'bool' when building for Linux using Bazel

I'm compiling some C++ code that compiles fine for Android and iOS but fails under Linux. I've searched around and it looks like this kind of crash shows up when the implementer does something wrong; such as, using a reserved word. However I fail to see what I am doing wrong based on the error I'm getting.
In file included from external/rapidjson_artifact/include/rapidjson/document.h:20:0,
from src/main/cc/com/mycompany/serialization/JsonSerializer.h:4,
from bazel-out/k8-dbg/genfiles/src/main/java/com/mycompany/model/common/cc/com
/mycompany/model/common/Vector2d.h:13,
from bazel-out/k8-dbg/genfiles/src/main/java/com/mycompany/model/common/cc/com/mycompany/model/common/FastVector2d.h:10,
from src/main/cc/com/mycompany/api/gestures/primitives/CalculatedElementPosition.h:7,
from src/main/cc/com/mycompany/api/gestures/primitives/PointerInteraction.h:7,
from src/main/cc/com/mycompany/api/gestures/native/NativeUserInteractionHandler.h:10,
from src/main/cc/com/mycompany/linux/api/gestures/UserInteractionHandler.h:4,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.h:13,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.cc:1:
external/rapidjson_artifact/include/rapidjson/reader.h:189:15: error: expected unqualified-id before 'bool'
bool Bool(bool) { return static_cast<Override&>(*this).Default(); }
^~~~
external/rapidjson_artifact/include/rapidjson/reader.h:189:15: error: expected ')' before 'bool'
In file included from /usr/include/GL/glx.h:30:0,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.h:7,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.cc:1:
external/rapidjson_artifact/include/rapidjson/reader.h: In member function 'void rapidjson::GenericReader<SourceEncoding, TargetEncoding, StackAllocator>::ParseTrue(InputStream&, Handler&)':
external/rapidjson_artifact/include/rapidjson/reader.h:623:26: error: expected unqualified-id before 'int'
if (!handler.Bool(true))
^
external/rapidjson_artifact/include/rapidjson/reader.h:623:26: error: expected ')' before 'int'
external/rapidjson_artifact/include/rapidjson/reader.h: In member function 'void rapidjson::GenericReader<SourceEncoding, TargetEncoding, StackAllocator>::ParseFalse(InputStream&, Handler&)':
external/rapidjson_artifact/include/rapidjson/reader.h:636:26: error: expected unqualified-id before 'int'
if (!handler.Bool(false))
^
external/rapidjson_artifact/include/rapidjson/reader.h:636:26: error: expected ')' before 'int'
external/rapidjson_artifact/include/rapidjson/document.h: In member function 'bool rapidjson::GenericValue<Encoding, Allocator>::Accept(Handler&) const':
external/rapidjson_artifact/include/rapidjson/document.h:1539:44: error: expected unqualified-id before 'int'
case kFalseType: return handler.Bool(false);
^
external/rapidjson_artifact/include/rapidjson/document.h:1539:44: error: expected ';' before 'int'
external/rapidjson_artifact/include/rapidjson/document.h:1540:44: error: expected unqualified-id before 'int'
case kTrueType: return handler.Bool(true);
^
external/rapidjson_artifact/include/rapidjson/document.h:1540:44: error: expected ';' before 'int'
In file included from src/main/cc/com/mycompany/serialization/JsonSerializer.h:4:0,
from bazel-out/k8-dbg/genfiles/src/main/java/com/mycompany/model/common/cc/com/mycompany/model/common/Vector2d.h:13,
from bazel-out/k8-dbg/genfiles/src/main/java/com/mycompany/model/common/cc/com/mycompany/model/common/FastVector2d.h:10,
from src/main/cc/com/mycompany/api/gestures/primitives/CalculatedElementPosition.h:7,
from src/main/cc/com/mycompany/api/gestures/primitives/PointerInteraction.h:7,
from src/main/cc/com/mycompany/api/gestures/native/NativeUserInteractionHandler.h:10,
from src/main/cc/com/mycompany/linux/api/gestures/UserInteractionHandler.h:4,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.h:13,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.cc:1:
external/rapidjson_artifact/include/rapidjson/document.h: At global scope:
external/rapidjson_artifact/include/rapidjson/document.h:2028:15: error: expected unqualified-id before 'bool'
bool Bool(bool b) { new (stack_.template Push<ValueType>()) ValueType(b); return true; }
^~~~
external/rapidjson_artifact/include/rapidjson/document.h:2028:15: error: expected ')' before 'bool'
In file included from src/main/cc/com/mycompany/serialization/JsonSerializer.h:6:0,
from bazel-out/k8-dbg/genfiles/src/main/java/com/mycompany/model/common/cc/com/mycompany/model/common/Vector2d.h:13,
from bazel-out/k8-dbg/genfiles/src/main/java/com/mycompany/model/common/cc/com/mycompany/model/common/FastVector2d.h:10,
from src/main/cc/com/mycompany/api/gestures/primitives/CalculatedElementPosition.h:7,
from src/main/cc/com/mycompany/api/gestures/primitives/PointerInteraction.h:7,
from src/main/cc/com/mycompany/api/gestures/native/NativeUserInteractionHandler.h:10,
from src/main/cc/com/mycompany/linux/api/gestures/UserInteractionHandler.h:4,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.h:13,
from src/main/cc/com/mycompany/linux/api/opengl/OpenGlHandler.cc:1:
external/rapidjson_artifact/include/rapidjson/writer.h:109:15: error: expected unqualified-id before 'bool'
bool Bool(bool b) { Prefix(b ? kTrueType : kFalseType); return WriteBool(b); }
^~~~
external/rapidjson_artifact/include/rapidjson/writer.h:109:15: error: expected ')' before 'bool'
All the errors point to rapidjson but I highly doubt that is the problem. It is probably something I'm doing wrong.
Can someone suggest what I should look for to find the root cause?

Why do I need a 'template' keyword in a not dependent context?

I know I need a template keyword when calling a template method of a template in a depended context. This is quite clear to me.
Now, I have something like:
#include <repository/RepositoryManager.hpp>
#include <events/Manager.hpp>
#include <memory>
#include <boost/di.hpp>
namespace di = boost::di;
inline std::shared_ptr<RepositoryManager> createRepositoryManager(int p) {
(void)p;
auto injector = di::make_injector(
di::bind<events::Manager>().to<events::Manager>().in(di::singleton)
);
return injector.create<std::shared_ptr<RepositoryManager>>();
}
This compiles and works as expected but what I actually need is it to be a template but simply changing the definition like this:
template <typename Param>
inline std::shared_ptr<RepositoryManager> createRepositoryManager(Param p)
Gives me a bunch of errors:
In file included from x/main.cpp:7:0:
x/setup.hpp: In function ‘std::shared_ptr<RepositoryManager> createRepositoryManager(Param)’:
x/setup.hpp:19:53: error: expected primary-expression before ‘>’ token
di::bind<events::Manager>().to<events::Manager>().in(di::singleton)
^
x/setup.hpp:19:55: error: expected primary-expression before ‘)’ token
di::bind<events::Manager>().to<events::Manager>().in(di::singleton)
^
x/setup.hpp:21:59: error: expected primary-expression before ‘>’ token
return injector.create<std::shared_ptr<RepositoryManager>>();
^~
x/setup.hpp:21:62: error: expected primary-expression before ‘)’ token
return injector.create<std::shared_ptr<RepositoryManager>>();
^
I have figured out I can change the definition like this and all is good:
template <typename Param>
inline std::shared_ptr<RepositoryManager> createRepositoryManager(Param p) {
(void)p;
auto injector = di::make_injector(
di::bind<events::Manager>().template to<events::Manager>().in(di::singleton)
);
return injector.template create<std::shared_ptr<RepositoryManager>>();
}
I'd like, however, to understand why. The events::Manager and RepositoryManager are normal classes (complete, not templates). I don't see how I could be in a dependent context here unless there's some funny rule I do not understand.
Oh, and just out of curiosity I've tried the code below and it also compiles. I'm lost.
template <typename Param>
inline std::shared_ptr<RepositoryManager> createRepositoryManager(Param p) {
(void)p;
auto injector = di::make_injector();
return injector.create<std::shared_ptr<RepositoryManager>>();
}
Edit:
It has been marked as duplicate of: Where and why do I have to put the "template" and "typename" keywords?
Well, I've read that before asking and it still does not explain my situation (unless I'm really missing something). Neither template parameter type, nor parameter value is used here, so my understanding is I'm in an independent context and I should be able to call the templated methods just fine. So where am I wrong?

C++ expected `)' before ';' token expected primary-expression before ')' token

Hello there I am iplementingh a binary tree based on an underlying array.
My project is comprises a set of c++ files and the makefile for generating the compilation.
I am using g++ provided with DEV-C++ 4.9.9.2.
Upon launching compilation I get the following two set of errors.
AlberoBinariov.h: In member function bool AlberoBinariov<T>::figlioSinistroVuoto(typename Alberoa<T, int>::posizioneNodo)':
AlberoBinariov.h:198: error: expected)' before ';' token
AlberoBinariov.h:198: error: expected primary-expression before ')' token
AlberoBinariov.h:198: error: expected `;' before ')' token
AlberoBinariov.h: In member function bool AlberoBinariov<T>::figlioDestroVuoto(typename Alberoa<T, int>::posizioneNodo)':
AlberoBinariov.h:204: error: expected)' before ';' token
AlberoBinariov.h:204: error: expected )' before ';' token
AlberoBinariov.h:204: error: expected primary-expression before ')' token
AlberoBinariov.h:204: error: expected;' before ')' token
Interested portions of code are provided below:
template <class T>
bool AlberoBinariov<T>::figlioSinistroVuoto(posizioneNodo p)
{
return (figlioSinistro(p)==(posizioneNodo)P_NULL); //line 198
}
template <class T>
bool AlberoBinariov<T>::figlioDestroVuoto(posizioneNodo p)
{
return (figlioDestro(p)==((posizioneNodo)P_NULL)); //line 204
}
also for your convenince I have included the full source code at the link below.
https://filetea.me/t1sc3e60
Can you please let me know? thanks you in advance for your time. I look forward to hear from you.
Kind regards,
Gerald
PS: P_NULL is a NULL pointer constant declared in the Constants.h file.
You have 3 individual right parenthesis without their corresponding left parenthesis:
return (figlioDestro(p) == ((posizioneNodo)P_NULL)) /* -> */ )));
Change it to this:
return (figlioDestro(p) == ( (posizioneNodo)P_NULL ));

Why does gcc think that I am trying to make a function call in my template function signature?

GCC seem to think that I am trying to make a function call in my template function signature. Can anyone please tell me what is wrong with the following?
227 template<class edgeDecor, class vertexDecor, bool dir>
228 vector<Vertex<edgeDecor,vertexDecor,dir>> Graph<edgeDecor,vertexDecor,dir>::vertices()
229 {
230 return V;
231 };
GCC is giving the following:
graph.h:228: error: a function call cannot appear in a constant-expression
graph.h:228: error: template argument 3 is invalid
graph.h:228: error: template argument 1 is invalid
graph.h:228: error: template argument 2 is invalid
graph.h:229: error: expected unqualified-id before ‘{’ token
Thanks a lot.
You should put space between two >. >> is parsed as a bit-shift operator, not two closing brackets.