Consider the following code:
template <typename Datatype>
class MyClass
{
void doStuff();
template <typename AnotherDatatype>
void doTemplateStuff(AnotherDatatype Argument);
};
template <typename Datatype>
void MyClass<Datatype>::doStuff()
{
// ...
}
template <typename Datatype>
template <typename AnotherDatatype>
void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument)
{
// ...
}
The implementation for the second member function, doTemplateStuff, will not compile if I condense it like this:
template <typename Datatype, typename AnotherDatatype>
void MyClass<Datatype>::doTemplateStuff(AnotherDatatype Argument)
{
// ...
}
Why is this? Shouldn't separating template information by commas have the same effect as putting each typename on its own line? Or is there some subtle difference I'm not aware of...?
(Also, if someone can think of a better title please let me know.)
This is an excellent question. I don't know the specific reason that the standards committee decided to design templates this way, but I think it's a callback to lambda calculus and type theory. Mathematically speaking, there is an isomorphism between any function that takes two arguments and returns a value and a function that takes in a single argument, then returns a function that takes in yet another argument and then returns a value. For example:
λx. λy. x + y
is isomorphic with (but not identical to)
λ(x, y). x + y
where (x, y) is a single object representing the pair of x and y.
With C++ member function templates, C++ chose to use the first of these systems. You have to specify all the arguments for the outermost function, then, separately, all of the arguments for the innermost function. Mathematically this is equivalent to specifying all of the arguments at the same time in one argument list, but C++ didn't choose to do this.
Now, a really good question is why they didn't do this. I'm not fully sure of the rationale, but if I had to guess it's because of weird interactions with template specialization. If I can think of something specific I'll update this post.
Putting comma's between the template declaration tells the compiler to expect two template parameters. In your case, because the object is a template object when you declare the function as you do you're violating your own declaration. It's looking for that second template in the MyClass object, referencing the actual class declaration and realizing that it's an error.
Hence,
template<typename T, typename V>
struct Foo{
void bar();
};
template<typename T, typename V>
void Foo<T,V>::bar(){...}
is what it's expecting to see.
template<typename T>
struct Foo{
void bar();
}
template<typename T, typename V>
void Foo<T>::bar(){...}
is an error. It's wondering where that other template parameter came from.
If you want to do this you'll need to write the function right there:
template<typename T>
struct Foo{
template<typename V>
void bar(const V& _anInputValue){
cout << _anInputValue;
}
void baz();
};
template<typename T>
void Foo<T>::baz(){
cout << "Another function.";
}
Related
I am trying to write a class template that uses a parameter-pack and implements a member function for each type contained in the parameter-pack.
This is what I have so far:
template <typename...T>
class Myclass {
public:
void doSomething((Some_Operator_to_divorce?) T) {
/*
* Do Something
*/
std::cout << "I did something" << std::endl;
}
};
My goal is to have a class template that can be used in the following way:
Myclass<std::string, int, double> M;
M.doSomething("I am a String");
M.doSomething(1234);
M.doSomething(0.1234);
Where the class template mechanism will create an implementation for a doSomething(std::string x), a doSomething(int x) and a doSomething(double x) member function but not a doSomething(std::string x, int i, double f) member function.
I found a lot of examples in the web on the usability of parameter-packs, but I could not figure out if it can be used for my purpose, or if I totally misunderstood for what a parameter-pack can be used.
I thought that I need to unpack the parameter-pack but, after reading a lot of examples about unpacking parameter packs, I believe that this is not the right choice and it has a complete different meaning.
So, therefore, I am looking for a operation to "divorce" a parameter-pack.
There is no "operator" specifically that supports this, but what you're requesting can be done in a few different ways, depending on your requirements.
The only way to "extract" T types from a parameter pack of a class template with the purpose of implementing an overload-set of functions is to implement it using recursive inheritance, where each instance extracts one "T" type and implements the function, passing the rest on to the next implementation.
Something like:
// Extract first 'T', pass on 'Rest' to next type
template <typename T, typename...Rest>
class MyClassImpl : public MyClassImpl<Rest...>
{
public:
void doSomething(const T&) { ... }
using MyClassImpl<Rest...>::doSomething;
};
template <typename T>
class MyClassImpl<T> // end-case, no more 'Rest'
{
public:
void doSomething(const T&) { ... }
};
template <typename...Types>
class MyClass : public MyClassImpl<Types...>
{
public:
using MyClassImpl<Types...>::doSomething;
...
};
This will instantiate sizeof...(Types) class templates, where each one defines an overload for each T type.
This ensures that you get overload semantics -- such that passing an int can call a long overload, or will be ambiguous if there are two competing conversions.
However, if this is not necessary, then it'd be easier to enable the function with SFINAE using enable_if and a condition.
For exact comparisons, you could create an is_one_of trait that only ensures this exists if T is exactly one of the types. In C++17, this could be done with std::disjunction and std::is_same:
#include <type_traits>
// A trait to check that T is one of 'Types...'
template <typename T, typename...Types>
struct is_one_of : std::disjunction<std::is_same<T,Types>...>{};
Alternatively, you may want this to only work if it may work with convertible types -- which you might do something like:
template <typename T, typename...Types>
struct is_convertible_to_one_of : std::disjunction<std::is_convertible<T,Types>...>{};
The difference between the two is that if you passed a string literal to a MyClass<std::string>, it will work with the second option since it's convertible, but not the first option since it's exact. The deduced T type from the template will also be different, with the former being exactly one of Types..., and the latter being convertible (again, T may be const char*, but Types... may only contain std::string)
To work this together into your MyClass template, you just need to enable the condition with SFINAE using enable_if:
template <typename...Types>
class MyClass
{
public:
// only instantiates if 'T' is exactly one of 'Types...'
template <typename T, typename = std::enable_if_t<is_one_of<T, Types...>::value>>
void doSomething(const T&) { ... }
// or
// only instantiate if T is convertible to one of 'Types...'
template <typename T, typename = std::enable_if_t<is_convertible_to_one_of<T, Types...>::value>>
void doSomething(const T&) { ... }
};
Which solution works for you depends entirely on your requirements (overload semantics, exact calling convension, or conversion calling convension)
Edit: if you really wanted to get complex, you can also merge the two approaches... Make a type trait to determine what type would be called from an overload, and use this to construct a function template of a specific underlying type.
This is similar to how variant needs to be implemented, since it has a U constructor that considers all types as an overload set:
// create an overload set of all functions, and return a unique index for
// each return type
template <std::size_t I, typename...Types>
struct overload_set_impl;
template <std::size_t I, typename T0, typename...Types>
struct overload_set_impl<I,T0,Types...>
: overload_set_impl<I+1,Types...>
{
using overload_set_impl<I+1,Types...>::operator();
std::integral_constant<std::size_t,I> operator()(T0);
};
template <typename...Types>
struct overload_set : overload_set_impl<0,Types...> {};
// get the index that would be returned from invoking all overloads with a T
template <typename T, typename...Types>
struct index_of_overload : decltype(std::declval<overload_set<Types...>>()(std::declval<T>())){};
// Get the element from the above test
template <typename T, typename...Types>
struct constructible_overload
: std::tuple_element<index_of_overload<T, Types...>::value, std::tuple<Types...>>{};
template <typename T, typename...Types>
using constructible_overload_t
= typename constructible_overload<T, Types...>::type;
And then use this with the second approach of having a function template:
template <typename...Types>
class MyClass {
public:
// still accept any type that is convertible
template <typename T, typename = std::enable_if_t<is_convertible_to_one_of<T, Types...>::value>>
void doSomething(const T& v)
{
// converts to the specific overloaded type, and call it
using type = constructible_overload_t<T, Types...>;
doSomethingImpl<type>(v);
}
private:
template <typename T>
void doSomethingImpl(const T&) { ... }
This last approach does it two-phase; it uses the first SFINAE condition to ensure it can be converted, and then determines the appropriate type to treat it as and delegates it to the real (private) implementation.
This is much more complex, but can achieve the overload-like semantics without actually requiring recursive implementation in the type creating it.
If we have a standard class:
class Foo {
public:
int fooVar = 10;
int getFooVar();
}
The implementation for getFooVar() would be:
int Foo::getFooVar() {
return fooVar;
}
But in a templated class:
template <class T>
class Bar {
public:
int barVar = 10;
int getBarVar();
}
The implementation for getBarVar() must be:
template <class T>
int Bar<T>::getBarVar(){
return barVar();
}
Why must we have the template <class T> line before the function implementation of getBarVar and Bar<T>:: (as opposed to just Bar::), considering the fact that the function doesn't use any templated variables?
You need it because Bar is not a class, it's a template. Bar<T> is the class.
Bar itself is a template, as the other answers said.
But let's now assume that you don't need it, after all, you specified this, and I added another template argument:
template<typename T1, typename T2>
class Bar
{
void something();
};
Why:
template<typename T1, typename T2>
void Bar<T1, T2>::something(){}
And not:
void Bar::something(){}
What would happen if you wanted to specialize your implementation for one type T1, but not the other one? You would need to add that information. And that's where this template declaration comes into play and why you also need it for the general implementation (IMHO).
template<typename T>
void Bar<T, int>::something(){}
When you instantiate the class, the compiler checks if implementations are there. But at the time you write the code, the final type (i.e. the instantiated type) is not known.
Hence the compiler instantiates the definitions for you, and if the compiler should instantiate something it needs to be templated.
Any answer to this question boils down to "because the standard says so". However, instead of reciting standardese, let's examine what else is forbidden (because the errors help us understand what the language expects). The "single template" case is exhausted pretty quickly, so let's consider the following:
template<class T>
class A
{
template<class X>
void foo(X);
};
Maybe we can use a single template argument for both?
template<class U>
void A<U>::foo(U u)
{
return;
}
error: out-of-line definition of 'foo' does not match any declaration in 'A<T>'
No, we cannot. Well, maybe like this?
template<class U>
void A<U>::foo<U>(U u)
{
return;
}
error: cannot specialize a member of an unspecialized template
No. And this?
template<class U, class V>
void A<U>::foo(V u)
{
return;
}
error: too many template parameters in template redeclaration
How about using a default to emulate the matching?
template<class U>
template<class V = U>
void A<U>::foo(V u)
{
return;
}
error: cannot add a default template argument to the definition of a member of a class template
Clearly, the compiler is worried about matching the declaration. That's because the compiler doesn't match template definitions to specific calls (as one might be used to from a functional language) but to the template declaration. (Code so far here).
So on a basic level, the answer is "because the template definition must match the template declaration". This still leaves open the question "why can we not just omit the class template parameters then?" (as far as I can tell no ambiguity for the template can exist so repeating the template parameters does not help) though...
Consider a function template declaration
tempalte <typename T>
void foo();
now a definition
void foo() { std::cout << "Hello World"; }
is either a specialization of the above template or an overload. You have to pick either of the two. For example
#include <iostream>
template <typename T>
void foo();
void foo() { std::cout << "overload\n"; }
template <typename T>
void foo() { std::cout << "specialization\n"; }
int main() {
foo();
foo<int>();
}
Prints:
overload
specialization
The short answer to your question is: Thats how the rules are, though if you could ommit the template <typename T> from a definition of the template, a different way would be required to define an overload.
I wondered if there was any advantages of declaring templates function out of line vs in the class.
I'm trying to get a clear understanding of the pros and cons of the two syntax.
Here's an example:
Out of line:
template<typename T>
struct MyType {
template<typename... Args>
void test(Args...) const;
};
template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
// do things
}
Vs in class:
template<typename T>
struct MyType {
template<typename... Args>
void test(Args... args) const {
// do things
}
};
Are there language features that are easier to use with the first or second version? Does the first version would get in the way when using default template arguments or enable_if? I would like to see comparisons of how those two cases are playing with different language features like sfinae, and maybe potential future features (modules?).
Taking compiler specific behavior into account can be interesting too. I think MSVC needs inline in some places with the first code snippet, but I'm not sure.
EDIT: I know there is no difference on how these features works, that this is mostly a matter of taste. I want to see how both syntaxes plays with different techniques, and the advantage of one over the other. I see mostly answers that favors one over another, but I really want to get both sides. A more objective answer would be better.
There is no difference between the two versions regarding default template arguments, SFINAE or std::enable_if as overload resolution and substitution of template arguments work the same way for both of them. I also don't see any reason why there should be a difference with modules, as they don't change the fact that the compiler needs to see the full definition of the member functions anyway.
Readability
One major advantage of the out-of-line version is readability. You can just declare and document the member functions and even move the definitions to a separate file that is included in the end. This makes it so that the reader of your class template doesn't have to skip over a potentially large number of implementation details and can just read the summary.
For your particular example you could have the definitions
template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
// do things
}
in a file called MyType_impl.h and then have the file MyType.h contain just the declaration
template<typename T>
struct MyType {
template<typename... Args>
void test(Args...) const;
};
#include "MyType_impl.h"
If MyType.h contains enough documentation of the functions of MyType most of the time users of that class don't need to look into the definitions in MyType_impl.h.
Expressiveness
But it is not just increased readibility that differentiates out-of-line and in-class definitions. While every in-class definition can easily be moved to an out-of-line definition, the converse isn't true. I.e. out-of-line definitions are more expressive that in-class definitions. This happens when you have tightly coupled classes that rely on the functionality of each other so that a forward declaration doesn't suffice.
One such case is e.g. the command pattern if you want it to support chaining of commands and have it support user defined-functions and functors without them having to inherit from some base class. So such a Command is essentially an "improved" version of std::function.
This means that the Command class needs some form of type erasure which I'll omit here, but I can add it if someone really would like me to include it.
template <typename T, typename R> // T is the input type, R is the return type
class Command {
public:
template <typename U>
Command(U const&); // type erasing constructor, SFINAE omitted here
Command(Command<T, R> const&) // copy constructor that makes a deep copy of the unique_ptr
template <typename U>
Command<T, U> then(Command<R, U> next); // chaining two commands
R operator()(T const&); // function call operator to execute command
private:
class concept_t; // abstract type erasure class, omitted
template <typename U>
class model_t : public concept_t; // concrete type erasure class for type U, omitted
std::unique_ptr<concept_t> _impl;
};
So how would you implement .then? The easiest way is to have a helper class that stores the original Command and the Command to execute after that and just calls both of their call operators in sequence:
template <typename T, typename R, typename U>
class CommandThenHelper {
public:
CommandThenHelper(Command<T,R>, Command<R,U>);
U operator() (T const& val) {
return _snd(_fst(val));
}
private:
Command<T, R> _fst;
Command<R, U> _snd;
};
Note that Command cannot be an incomplete type at the point of this definition, as the compiler needs to know that Command<T,R> and Command<R, U> implement a call operator as well as their size, so a forward declaration is not sufficient here. Even if you were to store the member commands by pointer, for the definition of operator() you absolutely need the full declaration of Command.
With this helper we can implement Command<T,R>::then:
template <typename T, R>
template <typename U>
Command<T, U> Command<T,R>::then(Command<R, U> next) {
// this will implicitly invoke the type erasure constructor of Command<T, U>
return CommandNextHelper<T, R, U>(*this, next);
}
Again, note that this doesn't work if CommandNextHelper is only forward declared because the compiler needs to know the declaration of the constructor for CommandNextHelper. Since we already know that the class declaration of Command has to come before the declaration of CommandNextHelper, this means you simply cannot define the .then function in-class. The definition of it has to come after the declaration of CommandNextHelper.
I know that this is not a simple example, but I couldn't think of a simpler one because that issue mostly comes up when you absolutely have to define some operator as a class member. This applies mostly to operator() and operator[] in expession templates since these operators cannot be defined as non-members.
Conclusion
So to conclude: It is mostly a matter of taste which one you prefer, as there isn't much of a difference between the two. Only if you have circular dependencies among classes you can't use in-class defintion for all of the member functions. I personally prefer out-of-line definitions anyway, since the trick to outsource the function declarations can also help with documentation generating tools such as doxygen, which will then only create documentation for the actual class and not for additional helpers that are defined and declared in another file.
Edit
If I understand your edit to the original question correctly, you'd like to see how general SFINAE, std::enable_if and default template parameters looks like for both of the variants. The declarations look exactly the same, only for the definitions you have to drop default parameters if there are any.
Default template parameters
template <typename T = int>
class A {
template <typename U = void*>
void someFunction(U val) {
// do something
}
};
vs
template <typename T = int>
class A {
template <typename U = void*>
void someFunction(U val);
};
template <typename T>
template <typename U>
void A<T>::someFunction(U val) {
// do something
}
enable_if in default template parameter
template <typename T>
class A {
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
bool someFunction(U const& val) {
// do some stuff here
}
};
vs
template <typename T>
class A {
template <typename U, typename = std::enable_if_t<std::is_convertible<U, T>::value>>
bool someFunction(U const& val);
};
template <typename T>
template <typename U, typename> // note the missing default here
bool A<T>::someFunction(U const& val) {
// do some stuff here
}
enable_if as non-type template parameter
template <typename T>
class A {
template <typename U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
bool someFunction(U const& val) {
// do some stuff here
}
};
vs
template <typename T>
class A {
template <typename U, std::enable_if_t<std::is_convertible<U, T>::value, int> = 0>
bool someFunction(U const& val);
};
template <typename T>
template <typename U, std::enable_if_t<std::is_convertible<U, T>::value, int>>
bool A<T>::someFunction(U const& val) {
// do some stuff here
}
Again, it is just missing the default parameter 0.
SFINAE in return type
template <typename T>
class A {
template <typename U>
decltype(foo(std::declval<U>())) someFunction(U val) {
// do something
}
template <typename U>
decltype(bar(std::declval<U>())) someFunction(U val) {
// do something else
}
};
vs
template <typename T>
class A {
template <typename U>
decltype(foo(std::declval<U>())) someFunction(U val);
template <typename U>
decltype(bar(std::declval<U>())) someFunction(U val);
};
template <typename T>
template <typename U>
decltype(foo(std::declval<U>())) A<T>::someFunction(U val) {
// do something
}
template <typename T>
template <typename U>
decltype(bar(std::declval<U>())) A<T>::someFunction(U val) {
// do something else
}
This time, since there are no default parameters, both declaration and definition actually look the same.
Are there language features that are easier to use with the first or second version?
Quite trivial a case, but it's worth to be mentioned: specializations.
As an example, you can do this with out-of-line definition:
template<typename T>
struct MyType {
template<typename... Args>
void test(Args...) const;
// Some other functions...
};
template<typename T>
template<typename... Args>
void MyType<T>::test(Args... args) const {
// do things
}
// Out-of-line definition for all the other functions...
template<>
template<typename... Args>
void MyType<int>::test(Args... args) const {
// do slightly different things in test
// and in test only for MyType<int>
}
If you want to do the same with in-class definitions only, you have to duplicate the code for all the other functions of MyType (supposing test is the only function you want to specialize, of course).
As an example:
template<>
struct MyType<int> {
template<typename... Args>
void test(Args...) const {
// Specialized function
}
// Copy-and-paste of all the other functions...
};
Of course, you can still mix in-class and out-of-line definitions to do that and you have the same amount of code of the full out-of-line version.
Anyway I assumed you are oriented towards full in-class and full out-of-line solutions, thus mixed ones are not viable.
Another thing that you can do with out-of-line class definitions and you cannot do with in-class definitions at all is function template specializations.
Of course, you can put the primary definition in-class, but all the specializations must be put out-of-line.
In this case, the answer to the above mentioned question is: there exist even features of the language that you cannot use with one of the version.
As an example, consider the following code:
struct S {
template<typename>
void f();
};
template<>
void S::f<int>() {}
int main() {
S s;
s.f<int>();
}
Suppose the designer of the class wants to provide an implementation for f only for a few specific types.
He simply can't do that with in-class definitions.
Finally, out-of-line definitions help to break circular dependencies.
This has been already mentioned in most of the other answers and it doesn't worth it to give another example.
Separating the declaration from the implementation allows you to do this:
// file bar.h
// headers required by declaration
#include "foo.h"
// template declaration
template<class T> void bar(foo);
// headers required by the definition
#include "baz.h"
// template definition
template<class T> void bar(foo) {
baz();
// ...
}
Now, what would make this useful? Well, the header baz.h may now include bar.h and depend on bar and other declarations, even though the implementation of bar depends on baz.h.
If the function template was defined inline, it would have to include baz.h before declaring bar, and if baz.h depends on bar, then you'd have a circular dependency.
Besides resolving circular dependencies, defining functions (whether template or not) out-of-line, leaves the declarations in a form that works effectively as a table of contents, which is easier for programmers to read than declarations sprinkled across a header full of definitions. This advantage diminishes when you use specialized programming tools that provide a structured overview of the header.
I tend to always merge them - but you can't do that if they are codependent. For regular code you usually put the code in a .cpp file, but for templates that whole concept doesn't really apply (and makes for repeated function prototypes). Example:
template <typename T>
struct A {
B<T>* b;
void f() { b->Check<T>(); }
};
template <typename T>
struct B {
A<T>* a;
void g() { a->f(); }
};
Of course this is a contrived example but replace the functions with something else. These two classes require each other to be defined before they can be used. If you use a forward declaration of the template class, you still cannot include the function implementation for one of them. That's a great reason to put them out of line, which 100% fixes this every time.
One alternative is to make one of these an inner class of the other. The inner class can reach out into the outer class beyond its own definition point for functions so the problem is kind of hidden, which is usable in most cases when you have these codependent classes.
My template-fu is rather weak. I have this code:
template<typename T>
void Foo(void(*func)(T*)) { }
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
...but I'd like something more readable than C's nasty function pointer syntax of void(*func)(T*).
Someone on my team suggested this:
template<typename T>
struct Types
{
typedef void Func(T*);
};
template<typename T>
void Foo2(typename Types<T>::Func* func) {}
void Test2()
{
Foo2(Callback); // could not deduce template argument for 'T'
Foo2<int>(Callback); // ok
}
(I'm still debating whether this is actually more readable, but that's a separate issue.)
How can I help the compiler figure out what T is without needing to explicitly specify it in the caller?
You can extract T from the function type using a traits class.
template<class F>
struct CallbackTraits;
template<class T>
struct CallbackTraits<void(*)(T)>
{
typedef T ArgumentType;
};
Your example can be modified like this:
template<typename F>
void Foo(F func)
{
typedef typename CallbackTraits<F>::ArgumentType T;
}
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
This technique is used in the boost type-traits library:
http://www.boost.org/doc/libs/1_57_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html
This blog post goes into a bit more detail about the implementation of the technique:
https://functionalcpp.wordpress.com/2013/08/05/function-traits/
Unfortunately this approach hides the information in the signature of Foo about the constraints on the argument passed in. In the above example the argument must be a function of type void(T*).
This alternative syntax does the same as the original example while being slightly more readable:
template<typename T>
void Foo(void func(T*)) { }
Another alternative syntax that may be more readable can be achieved using c++11's alias templates as follows:
template<typename T>
using Identity = T;
template<typename T>
void Foo(Identity<void(T*)> func) { }
Unforunately the latest MSVC fails to compile this, reporting an internal compiler error.
You won't be able to deduce the type based on a nested name: there is no reason why different instantiations of the outer type won't define an identical inner type. You could use a using alias, though:
template <typename T>
using Function = auto (*)(T*) -> void;
template <typename T>
void Foo(Function<T>) {
}
Personally, I would recommend against using any of that, however: in practice it seems much more advisable to actually take a function object which later allows using object with suitable function call operators to be used. For callbacks it is quite common that you'll need to pass in some auxiliary data. That is, you would either use an unconstrained template or one which takes a type-erased type, depending on what you want to do exactly:
template <typename Fun>
void Unconstrained(Fun fun) {
}
template <typename T>
void TypeErased(std::function<void(T*)> fun) {
}
The unconstrained version has the advantage that it can potentially inline the function call but it has the disadvantage that every function object type creates a new instantiation and that the argument types are likely to vary. The type-erased version effectively has to do something like a virtual function call but there is just one instantiation of the function template (per argument type T, of course).
Admittedly, the type-erased version's type won't be deduced from a function pointer (or any other argument which isn't a std::function<void(X*)>), i.e., you may want to have a forwarding function
template <typename T>
void TypeErased(Function<T> fun) {
TypeErased(std::function<void(T)>(fun));
}
In C++98 and C++03 template argument deduction only works with functions (and methods).
I don't think the picture changed in the more recent standards.
Suppose we have this code:
template <class T, void (*u)(T&)>
void Foo()
{
// store the function u internally . . .
}
There are reasons to do something like this and I won't attempt to go into them. However, is there any way to avoid having to specify type T when calling Foo()? For example, to compile, one normally needs:
Foo<int, MyIntFunction>();
But if this int can be deduced from the function pointer, is this possible:
Foo<MyIntFunction>();
EDIT I'm aware of the solution to pass the actual function pointer in as a function parameter, however this is not desired here as it has some perf drawbacks in intensive loop.
In this example u is not a function pointer, it's a type (the signature of a function pointer). If you want to store a function pointer you need to pass it.
template<class T, class F = void(*)(T&)>
void Foo(F f)
{
// store the function pointer f here
}
called like so:
struct SomeType {};
void bar(SomeType& x);
Foo(&bar);
Is this what you mean to do?
Short answer: I don't think it is possible.
Long one.. When calling a template function, you cannot omit the first parameter and specify the second: the compiler would try to match your MyIntFunction to the template parameter T. Generally, you can specify the first, but omit the second if the compiler can infer the second template parameter. In this case, this is not an option however, because you want to specify the second parameter explicitly.
The second template parameter has a dependency (T) on the first template parameter. Therefore, reversing the order of the template parameters is also not an option.
Your best bet would be to define it in a way similar to what Richard suggested:
template<class T>
void Foo(T f)
{
int a(1);
f(a); // this forces f to be a function taking an int as parameter
}
Here is a dirty implementation which basically does what the OP was asking for. It depends on too many assumptions, but could be at least something to discuss. The idea is to specify in advance all possible types which can serve as function argument, and then deduce this type.
#include<iostream>
template<typename T>
struct TD; //type display
template<typename FunctionType, typename T, typename ... Ts>
struct ArgumentDeduction
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, typename ArgumentDeduction<FunctionType, Ts ...>::type
>::type type;
};
template<typename FunctionType, typename T>
struct ArgumentDeduction<FunctionType, T>
{
typedef typename std::conditional<std::is_same<void, typename std::result_of<FunctionType(T)>::type>::value
, T
, void
>::type type;
};
template<typename FunctionType
, typename T = typename ArgumentDeduction<FunctionType, int, double>::type >
void foo()
{
TD<T>();
}
struct AvoidConversion
{
struct DummyType{};
template<typename T> DummyType operator()(T x) { return DummyType(); }
};
struct Bar : public AvoidConversion
{
using AvoidConversion::operator();
void operator()(int x);
//void operator()(double x); //try also this
};
int main()
{
foo<Bar>(); //calls the foo<Bar,int> version
}
One main assumption here is the form of the Bar functor, which in principle accepts any type, but has a relevant implementation of type void only for the single allowed type.
Again, I don't think this is rather useful, but I guess this comes closest to the OP's question up to now.
DEMO
EDIT: Otherwise, i.e. without AvoidConversion in the code above, the compiler will perform an implicit conversion and the argument deduction gives true for all types which are convertible into each other (such that, e.g., int is deduced when there is only a function taking double).
If someone sees a way to avoid this ugly AvoidConversion hack and deduce the parameter type somehow more elegant, I would be interested in seeing that.