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
How to Sort an Stl Map by Value
What Does the Standard Say About How Calling Clear on a Vector Changes the Capacity
Difference Between C++03 Throw() Specifier C++11 Noexcept
Std::Set with User Defined Type, How to Ensure No Duplicates
C++ Sort Keeping Track of Indices
How to Recover View Space Position Given View Space Depth Value and Ndc Xy
Error Lnk1104: Cannot Open File 'Debug\Myprojectlib.Lib'
Why Is 'I = ++I + 1' Unspecified Behavior
C++ Function Pointer (Class Member) to Non-Static Member Function
Overloading Operator<<: Cannot Bind Lvalue to 'Std::Basic_Ostream<Char>&&'
Isdigit(C) - a Char or Int Type
Why Are Memcpy() and Memmove() Faster Than Pointer Increments
How Is a Vector's Data Aligned
Search for a Struct Item in a Vector by Member Data