I have a template class CFoo using the following types
enum My_Types {t1,t2};
with the specialization given by
template<My_Types T>
class CFoo
{
public:
CFoo()
{
std::cerr<<"ERROR:....";
exit(1);
}
};
template<>
class CFoo<t1>
{
....
};
In addition I have a function which uses a CFoo object as an argument
template<class T>
void foo1 ( const T &CfooObj,...);
Now I need a pointer to foo1, so I have to specify the template argument
void (*foo1_pointer) ( const CFoo< t1 >&,...);
But the following seems not to be correct (" no matches converting function foo1..."):
foo1_pointer=&foo1;
How to pass the pointer of this template function correctly?
This is probably due to the old version of your GCC compiler. This code compiles fine on GCC 4.7.2, Clang 3.2, ICC 13.0.1, and VS10:
#include <iostream>
enum My_Types {t1,t2};
template<My_Types T>
class CFoo { /* ... */ };
template<> class CFoo<t1> { /* ... */ };
template<class T>
void foo1 (const T &, ...) { /* ... */ }
int main()
{
void (*foo1_pointer) (const CFoo< t1 >&, ...);
foo1_pointer = &foo1;
}
The compiler should be able to deduce the template arguments of foo1 when taking its address from the type of the function pointer it is assigned to. Per Paragraph 14.8.2.3/1 of the C++11 Standard:
Template arguments can be deduced from the type specified when taking the address of an overloaded function (13.4). The function template’s function type and the specified type are used as the types of P and A, and the deduction is done as described in 14.8.2.5.
And also, per Paragraph 13.4/1:
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a pointer to function or a pointer to member function for a specific function from the overload set. A function template name is considered to name a set of overloaded functions in such contexts. The function selected is the one whose type is identical to the function type of the target type required in the context. [...]
The assignment should be like this:
foo1_pointer = &foo1<CFoo<t1>>;
You can just write foo1<CFoo<t1>>. Or just foo1 (works with g++ 4.7.2).
Related
I think this code is valid C++. MSVC agrees but gcc seems to disagree. Are MSVC and I wrong? (Or should I be typing something slightly different?)
#include <iostream>
#include <string>
#include <vector>
#include <functional>
template <typename T>
struct S
{
template <typename R>
void f(std::function<R(T)> fn)
{
auto p = &fn;
++p;
}
template <typename R>
void g(std::function<R(void)> fn)
{
auto p = &fn;
++p;
}
};
void f()
{
S<void> s;
auto p = &s;
++p;
}
int main()
{
f();
}
error message:
<source>: In instantiation of 'struct S<void>':
<source>:26:11: required from here
<source>:11:8: error: invalid parameter type 'void'
void f(std::function<R(T)> fn)
^
<source>:11:8: error: in declaration 'void S<T>::f(std::function<R(T)>)'
Compiler returned: 1
gcc seems to be fine if I write the literal, void, as the parameter type (see parameter to function g()). But it is unhappy if I write T and then resolve T to void (see parameter to function f()).
No, your example is not valid C++. The rule that allows (void) to be a function parameter list with no parameters is found in Standard section [dcl.fct], paragraph 4:
A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list. Except for this special case, a parameter shall not have type cv void.
The key for your question is the word "non-dependent", meaning not depending on a template parameter. The requirement was probably written this way because it would be too surprising to write the function declaration void func(T); within a template, expecting it to always be a function type taking exactly one parameter, and then find in one case it might not be.
So:
void f1(void); // okay - classic style from C
void f2(void nothing); // error - the phony "void" parameter cannot be named
void f3(const void); // error - const void is a different type
using VoidType = void;
void f4(VoidType); // okay - using a non-dependent type alias
template <typename T>
void f5(T);
void (*fptr)(void) = f5<void>; // error - dependent parameter type cannot be void
I would like to better understand why automatic template deduction (applied when compiled with g++ -std=c++17) works in the first three lines in main(), but fails in the fourth. Is there any chance it will be accepted by compilers in the near future?
template <typename P = void>
class A {
public:
void f1() {}
};
template<typename C>
void g() {}
int main() {
A<> a; // works
A aa; // works
g<A<>>(); // works
g<A>(); // fails
return 0;
}
It's just a matter of signature. Basically you're passing the wrong type.
Both A a and A<> a mean you want an instance of A with the default template parameter value, that is, you end up with A< void >.
The function g< C >() accepts a template parameter which happens to be a type, not another templated type. When you invoke it with A<>, you tell the compiler that you want to use "the instantiation" of the templated type A, which is valid. When you invoke it with A you tell the compiler you want to invoke g< C >() with C being a templated type which does not fit its signature.
If you declare/define g() like so template <typename <typename> TTemplatedType> g() it will accepts to be invoked like this g< A >() but g< A<> >() will fail because now it no longer wants something else than a templated type.
With C++17, template argument deduction is also performed when the name of a class template is used as the type of an object being constructed.
Nothing changes for explicit type inside template.
I'm experimenting with resolving the address of an overloaded function (bar) in the context of another function's parameter (foo1/foo2).
struct Baz {};
int bar() { return 0; }
float bar(int) { return 0.0f; }
void bar(Baz *) {}
void foo1(void (&)(Baz *)) {}
template <class T, class D>
auto foo2(D *d) -> void_t<decltype(d(std::declval<T*>()))> {}
int main() {
foo1(bar); // Works
foo2<Baz>(bar); // Fails
}
There's no trouble with foo1, which specifies bar's type explicitly.
However, foo2, which disable itself via SFINAE for all but one version of bar, fails to compile with the following message :
main.cpp:19:5: fatal error: no matching function for call to 'foo2'
foo2<Baz>(bar); // Fails
^~~~~~~~~
main.cpp:15:6: note: candidate template ignored: couldn't infer template argument 'D'
auto foo2(D *d) -> void_t<decltype(d(std::declval<T*>()))> {}
^
1 error generated.
It is my understanding that C++ cannot resolve the overloaded function's address and perform template argument deduction at the same time.
Is that the cause ? Is there a way to make foo2<Baz>(bar); (or something similar) compile ?
As mentioned in the comments, [14.8.2.1/6] (working draft, deducing template arguments from a function call) rules in this case (emphasis mine):
When P is a function type, function pointer type, or pointer to member function type:
If the argument is an overload set containing one or more function templates, the parameter is treated as a non-deduced context.
If the argument is an overload set (not containing function templates), trial argument deduction is attempted using each of the members of the set. If deduction succeeds for only one of the overload set members, that member is used as the argument value for the deduction. If deduction succeeds for more than one member of the overload set the parameter is treated as a non-deduced context.
SFINAE takes its part to the game once the deduction is over, so it doesn't help to work around the standard's rules.
For further details, you can see the examples at the end of the bullet linked above.
About your last question:
Is there a way to make foo2<Baz>(bar); (or something similar) compile ?
Two possible alternatives:
If you don't want to modify the definition of foo2, you can invoke it as:
foo2<Baz>(static_cast<void(*)(Baz *)>(bar));
This way you explicitly pick a function out of the overload set.
If modifying foo2 is allowed, you can rewrite it as:
template <class T, class R>
auto foo2(R(*d)(T*)) {}
It's more or less what you had before, no decltype in this case and a return type you can freely ignore.
Actually you don't need to use any SFINAE'd function to do that, deduction is enough.
In this case foo2<Baz>(bar); is correctly resolved.
Some kind of the general answer is here: Expression SFINAE to overload on type of passed function pointer
For the practical case, there's no need to use type traits or decltype() - the good old overload resolution will select the most appropriate function for you and break it into 'arguments' and 'return type'. Just enumerate all possible calling conventions
// Common functions
template <class T, typename R> void foo2(R(*)(T*)) {}
// Different calling conventions
#ifdef _W64
template <class T, typename R> void foo2(R(__vectorcall *)(T*)) {}
#else
template <class T, typename R> void foo2(R(__stdcall *)(T*)) {}
#endif
// Lambdas
template <class T, class D>
auto foo2(const D &d) -> void_t<decltype(d(std::declval<T*>()))> {}
It could be useful to wrap them in a templated structure
template<typename... T>
struct Foo2 {
// Common functions
template <typename R> static void foo2(R(*)(T*...)) {}
...
};
Zoo2<Baz>::foo2(bar);
Although, it will require more code for member functions as they have modifiers (const, volatile, &&)
Here is some code from a presentation about async tasks in C++
template <class T> class Future<T>{
//something
void foo(std::function<void(T)> cb);
//something
};
What does void(T) mean?
What does void(T) mean?
That specifies a function type; specifically, a function taking a single parameter of type T, and returning nothing. In general, type specifiers for complex types look like their corresponding variable declarations, but without a variable name:
void f(T); // declare a function
void(T) // specifier for a function type
int a[42]; // declare an array
int[42] // specifier for an array type
In this case, the function type is used to specify the signature of the function-call operator of the std::function:
void operator()(T);
so that the function object can be used like a function with that type:
T some_t;
cb(some_t); // usable like a function taking `T`
cb is a std::function whose operator() takes a T and returns void.
void(T) is a function signature (type)
Note the signature is not a pointer to a function, not a pointer to a member function and no lambda:
#include<functional>
void a(int) {}
struct B {
void f(int) {}
};
int main() {
std::function<void(int)> fn;
fn = a;
B b;
fn = std::bind(&B::f, b, std::placeholders::_1);
auto lambda = [](int) {};
fn = lambda;
}
The explanation can be as follows based on the C++11 specifications : A parameter list consisting of a single unnamed parameter of non-dependent type void is equivalent to an empty parameter list.
void is not a valid argument type for a function, however T in void(T) is a dependent type, it depends on a template parameter. That way you can have no arguments in the function based on the parameter of the template.
Consider this template function:
template<typename ReturnT>
ReturnT foo(const std::function<ReturnT ()>& fun)
{
return fun();
}
Why isn't it possible for the compiler to deduce ReturnT from the passed call signature?
bool bar() { /* ... */ }
foo<bool>(bar); // works
foo(bar); // error: no matching function call
A function pointer of type bool (*)() can be converted to std::function<bool()> but is not the same type, so a conversion is needed. Before the compiler can check whether that conversion is possible it needs to deduce ReturnT as bool, but to do that it needs to already know that std::function<bool()> is a possible conversion, which isn't possible until it deduces ReturnT ... see the problem?
Also, consider that bool(*)() could also be converted to std::function<void()> or std::function<int()> ... which should be deduced?
Consider this simplification:
template<typename T>
struct function
{
template<typename U>
function(U) { }
};
template<typename T>
void foo(function<T>)
{ }
int main()
{
foo(1);
}
How can the compiler know whether you wanted to create function<int> or function<char> or function<void> when they can all be constructed from an int?
std::function<bool()> bar;
foo(bar); // works just fine
C++ can't deduce the return type from your function bar because it would have to know the type before it could find all the constructors that take your function pointer.
For example, who's to say that std::function<std::string()> doesn't have a constructor taking a bool (*)()?
The function bar is of type bool (*)() or so, that is: a normal pre-C++11 function type. I'm not that confident in C++11, but I guess the compiler does not see the connection between bool (*)() and const std::function<ReturnT()>&, even when the first can be implicitly converted into the second for ReturnT = bool.