Template Deduction for Function Based on Its Return Type

Template deduction for function based on its return type?

That cannot be done. The return type does not take part in type deduction, it is rather a result of having already matched the appropriate template signature. You can, nevertheless, hide it from most uses as:

// helper
template <typename T>
void Allocate( GCPtr<T>& p ) {
p = GC::Allocate<T>();
}

int main()
{
GCPtr<A> p = 0;
Allocate(p);
}

Whether that syntax is actually any better or worse than the initial GCPtr<A> p = GC::Allocate<A>() is another question.

P.S. c++11 will allow you to skip one of the type declarations:

auto p = GC::Allocate<A>();   // p is of type GCPtr<A>

Why is no deduction for template parameters only used as return type?

Generally it is not possible to deduce function based on its return type. But if you use automatic types conversion c++ feature then you could achieve what you need:

template <typename T>
T zero() { return 1; }

template <>
float zero<float>() { return 3.0f; }

struct Zero
{
template<typename T>
operator T()
{
return zero<T>();
}
};

int main()
{
int x = Zero();
float y = Zero();
return x + y;
}

First you create temporary object Zero(), and during assigment we use conversion operator to execute correct specialization of zero template function.

How to deduce template parameters based on return type?

Conversion operators can mimic that.

struct input {
const string &prompt;

input(const string &prompt) : prompt(prompt) {}

template <typename T>
operator T() const {
T _input;
cout << prompt;
cin >> _input;
return _input;
}
};

Mind however that this may not be applicable for every sort of operation. Plus, this is a fairly naive way of holding on the the prompt. You'd need to copy it proper if object lifetime issues become a concern.

Template type deduction in function return type

The compiler can't know that T0 is defined in MyClass<T>. So you need to properly qualify the reutrn type:

template <class T>
typename MyClass<T>::T0 MyClass<T>::getVar1() const {
return var1;
}

Alternatively, you can use a trailing return type, which you won't need to qualify either:

template <class T>
auto MyClass<T>::getVar1() const -> T0 {
return var1;
}

Function template return type deduction

I would recommend the:

template <class CType>
auto AliasGetNode(CType& cobject) -> decltype(cobject.getNode(0))
{
return cobject.getNode(0);
}

This should fairly work since c++11

Does template argument deduction takes return type into account?

struct A {
int value;

//conversion operator
template<class T>
operator T() {return static_cast<T>(value);}
};

A a{4};
float f = a; //conversion from A to float

How do write a templated free function depending on return type

Convert the return type rather than deduce it

You can create a conversion proxy object for your return type. This moves the return type deduction into a template conversion operation instead.

template <typename T>
struct foofoo {
T t_;
foofoo (T t) : t_(t) {}
template <typename U>
operator U () const { return static_cast<U>(t_); }
};

template <typename T>
foofoo<T> foo( T t )
{
return foofoo<T>(t);
}

Applied to MyClass, your getter could be implemented similarly:

template<typename T>
struct MyClass
{
T data;
foofoo<T> get() { return foofoo<T>(data); }
};

And then, this code would work just fine:

MyClass<int> m;
float v3 = m.get();

Deduce the return type of the getter

Now, to implement ff_get, it is mostly a trivial function implementation, except that the return type is now deduced from the get method itself. In C++11, you would use the trailing return type syntax.

template <typename T>
auto ff_get (T t) -> decltype(t.get())
{
return t.get();
}

Starting from C++ 14, you can drop the trailing return type altogether, since there is no ambiguity in the return type.

template <typename T>
auto ff_get (T t)
{
return t.get();
}

C++ Template; Auto deduction return type of function passed as template argument;

What you are looking for is result_type, probably:

//...
public:
using TValue = typename TGetter::result_type;
//...

Demo.

C++ function template type deduction from function parameter fails

All your questions have the same answer: the order of template parameter is important and, to explicate a template parameter, you have to explicate all template parameters before it.

When you write

template<typename C, Ret(C::* func)(ArgType)>
void connect(C& instance)

or

template<typename C, auto func>
void disconnect(C& instance)

the first template parameter can be deduced from instance, the second one can't be deduced so has to be explicated.

But, this is the problem, if you have to explicate a template parameter, you must explicate all template parameter before it.

So

signal.connect<&Window::kpEventHandler>(window); 

doesn't works because <&Window::kpEventHandler> explicate the first template parameter, that is C; and a &Window::kpEventHandler (that is a value) doesn't matches C, the first template argument (that has to be a type).

You have to explicate both template parameters, in the correct order, so

signal.connect<Window, &Window::kpEventHandler>(window);    
signal.disconnect<Window, &Window::kpEventHandler>(window);

Different if you place the non-deducible template parameter in first position

template<auto func, typename C>
void connect(C& instance)

This way you can explicate the first template parameter (the func value) and let the compiler to deduce C from the argument instance.

So you can write

signal.connect<&Window::kpEventHandler>(window);
signal.disconnect<&Window::kpEventHandler>(window);

but works also if you explicate the second template parameter too

signal.connect<&Window::kpEventHandler, Windows>(window);
signal.disconnect<&Window::kpEventHandler, Windows>(window);

Why isn't argument deduction allowed in function return type?

There's nothing language-lawery here: If you specify a return type (and not auto or T where T is a template type), that return type has to be valid. let me give you even a simpler, better example:

std::vector function() {
return std::vector<int>();
}

Obviously it fails to compile, even without fancy templates, auto and type deductions, because std::vector isn't a type, std::vector<int> is.

When you specify S as a return type you basically

  • Prevent the compiler from deducing the type itself
  • Specify an invalid return type, as S isn't a type, S<int> is.


Related Topics



Leave a reply



Submit