Class template parameter inference with constructor - c++

I have the following template class :
template <typename T>
struct timer
{
T period;
timer(T p) :
period(p)
{}
};
To instantiate it I need to do :
timer<double> t(double(0.0));
Is is possible to improve timer's class definition to allow this syntax :
timer t(double(0.0));
and have the compiler infer the double type from the constructor's argument ?

No, you can't do that. Type inference doesn't occur in those situations. You could use the auto keyword and a function template to make things easier though:
template<typename T>
timer<T> make_timer(T value) {
return value;
}
// let the compiler deduce double
auto t = make_timer(0.0);
Note that this use of the auto keyword is only valid in the C++11 standard.
Moreover, for this specific situation, you could typedef a double timer:
typedef timer<double> timer_d;
timer_d t(0.0);
Though I'd still go with the first solution, if you're able to use C++11.

No, it's not possible, deduction only works in functions. The usual solution is to write a make_ function which returns a new instance. This is C++11:
template <typename T>
timer<T> make_timer(T&& p) {
return timer<T>(std::forward<T>(p));
}
auto t = make_timer(0.0);

Related

Template argument deduction in function signature using guide

let's say you have a class A (C++17):
template<class T>
struct A
{
A() = default;
A(T t) : val(t)
{
}
A operator*(A a)
{
return A(a.val * this->val);
}
T val;
};
However, 99% of the time the value-type of A is going to be an int, so you use a deduction guide to reduce the verbosity:
A()->A<int>;
So that's cool, now you can define variables without the template list:
A myVar;
The problem I'm having is that it seems to break down when it comes to function signatures, for example the following requires use of a template argument list:
auto ASquared = [](A a, A b) { return a * b; };
error C2955: 'A': use of class template requires template argument
list
When I wanted it to deduce that A was A<int>.
My question is: is this an inherent limitation, or am I just missing a different deduction guide that could make this syntax work?
The language doesn't allow this. Deduction doesn't take place within a function signature because there's nothing to deduce from.

Type inference in explicit constructors

I'm toying with some type safety ideas using the following code which converts between related units . . .
#include <cmath>
#include <limits>
template <typename T>
class Pascal
{
private:
T val;
public:
explicit Pascal(const T val_)
{
val = val_;
}
operator T() const
{
return val;
}
};
template <typename T>
class dbSPL {
private:
T val;
public:
explicit dbSPL(const Pascal<T> p)
{
auto infProtect = std::numeric_limits<T>::min();
val = 20.0 * std::log10( infProtect + p / 20e-6 );
}
operator T() const
{
return val;
}
};
I want to know if it is possible to infer the template type from the constructor argument type, rather than explicitly declaring the template parameters. For example auto p = Pascal(0.5) rather than typing auto p = Pascal<double>(0.5), which would then lead to the neater dbSPL(Pascal(0.5)) over the more verbose dbSPL<double>(Pascal<double>(0.5)).
Use a helper function instead:
template <typename T>
dbSPL<T> make_dbspl(T t)
{
return dbSPL<T>(Pascal<T>(t));
}
int main()
{
auto dbspl = make_dbspl(0.5);
}
DEMO
One approach to solving this would be to create factory functions that are templated over the parameter types, and then return the dimensionalized types
As others said use wrapper function for this.
What I would add is that this approach is used even in c++ standard library, e.g. std::make_pair or std::make_shared in c++11. Reason for this is that when you write declaration like T t(x); then T is a type name and for templates type name contains template parameters. Additionally if T constructor is template itself then this constructor template parameters would be infered from type of x no template parameter of T itself.
I want to know if it is possible to infer the template type from the constructor argument type, rather than explicitly declaring the template parameters
No.
Neither the syntax nor the semantics of the language do or can support this.
Why not infer template parameter from constructor?
https://stackoverflow.com/a/6971914/560648
https://stackoverflow.com/a/7921464/560648
https://stackoverflow.com/a/29677772/560648

Function Templates vs. Auto Keyword

Can the auto keyword in C++11 replace function templates and specializations? If yes, what are the advantages of using template functions and specializations over simply typing a function parameter as auto?
template <typename T>
void myFunction(T &arg)
{
// ~
}
vs.
void myFunction(auto &arg)
{
// ~
}
In a nutshell, auto cannot be used in an effort to omit the actual types of function arguments, so stick with function templates and/or overloads. auto is legally used to automatically deduce the types of variables:
auto i=5;
Be very careful to understand the difference between the following, however:
auto x=...
auto &x=...
const auto &x=...
auto *px=...; // vs auto px=... (They are equivalent assuming what is being
// assigned can be deduced to an actual pointer.)
// etc...
It is also used for suffix return types:
template <typename T, typename U>
auto sum(const T &t, const U &u) -> decltype(t+u)
{
return t+u;
}
Can the auto keyword in C++11 replace function templates and specializations?
No. There are proposals to use the keyword for this purpose, but it's not in C++11, and I think C++14 will only allow it for polymorphic lambdas, not function templates.
If yes, What are the advantages of using template functions and specializations over simply typing a function parameter as auto.
You might still want a named template parameter if you want to refer to the type; that would be more convenient than std::remove_reference<decltype(arg)>::type or whatever.
The only thing which makes it the auto keyword different from template that is you cannot make a generic class using the auto keyword.
class B { auto a; auto b; }
When you create an object of the above class it will give you an error.
B b; // Give you an error because compiler cannot decide type so it can not be assigned default value to properties
Whereas using template you can make a generic class like this:
template <class T>
class B {
T a;
};
void main() {
B<int> b; //No Error
}

C++ failed template argument deduction. why?

template<typename T>
Ref<Iterator<T> > GetFilterIterator(Ref<Iterator<T> > i, boost::function<bool(T)> pred) {
return new FilterIterator<T>(i, pred);
}
Ref<Iterator<CWorm*> > x = GetFilterIterator(worms(), &CWorm::getLocal);
And worms() returns a Ref<Iterator<CWorm*> Ref> and there is bool CWorm::getLocal(); (which is a member function). And:
template<typename T> struct Ref {
// ...
};
template<typename T> struct Iterator {
// ...
};
This will fail to deduce the template argument:
Iter.h:272:27: note: candidate template ignored: failed template argument deduction [3]
Why?
If I call it with the specified template argument, i.e. GetFilterIterator<CWorm*>(worms(), &CWorm::getLocal), it doesn't complain. I wonder why it cannot deduce the template argument like this. And can I make it different somehow so that it would be able to automatically deduce the type?
Do you mean typname Iterator<T>::Ref for the type of the first parameter in the GetFilterIterator template declaration? If so, that is not a deducible context for template type parameters.
Consider:
template<>
struct Iterator<Foo> {
typedef int Ref;
};
template<>
struct Iterator<Bar> {
typedef int Ref;
};
GetFilterIterator(int(0),f);
Both Iterator<Foo>::Ref and Iterator<Bar>::Ref match the parameter passed to GetFilterIterator, an int. Which one should it pick? C++ disallows deducing template types from parameters like the one you've declared.
With the update to your question it looks like you do mean ::Ref<Iterator<T> >. I think that should be deducible then, and since the typedef Iterator<CWorm*>::Ref is ::Ref<Iterator<CWorm*> > it seems like it should be able to deduce T. I'm not sure why it's not working.
The compiler cannot deduce the template arguments because fitting to the parameters would mean a non-trivial conversion - first to Iterator<T> and then to Ref<Iterator<T> > which both require user-defined conversions. Also, directly converting the member function pointer to boost::function is similarly non-trivial for the compiler.
IBM has a list of supported template parameter deductions.
If you want your template arguments to be deduced automatically, you have to provide wrapper methods:
template <typename T>
Ref<Iterator<T> > makeIteratorRef(T val) {
return Ref<Iterator<T> >(Iterator<T>(val));
}
template <typename T>
boost::function<bool (T)> makeFn(bool (T::*fn) () const) {
boost::function<bool (T)> res = boost::bind(fn, _1);
return res;
}
...
Ref<Iterator<CWorm*> > x = GetFilterIterator(makeIteratorRef(worms()), makeFn(&CWorm::getLocal));
This way the compiler is capable of deducing the template parameters because no conversions are necessary.
By the way, I think you are overcomplicating simple things:
for (auto it = worms().begin(); it != worms().end(); ++it)
if (it->isLocal()) {
// Do something
}
This code is way more readable in C++ and even though it might not be as general it hardly makes the code worse.
Thanks to the hint from Xeo to here about that implicit type conversions are not allowed when deducing template arguments, I wondered wether the second parameter might cause problems here. I thought that it would do the type deduction from left to right and once the type is deducted, it is not a problem anymore (for the function pointer to boost::function cast).
It seems I was wrong and this was exactly the problem.
Another version of the same thing avoids the problem:
template<typename T>
struct PartialFuncWrapper {
::Ref<Iterator<T> > i;
PartialFuncWrapper(::Ref<Iterator<T> > _i) : i(_i) {}
typename Iterator<T>::Ref operator()(boost::function<bool(T)> pred) {
return new FilterIterator<T>(i, pred);
}
};
template<typename T>
PartialFuncWrapper<T> GetFilterIterator(::Ref<Iterator<T> > i) {
return PartialFuncWrapper<T>(i);
}
Then I can write:
Ref<Iterator<CWorm*> > x = GetFilterIterator(worms())(&CWorm::getLocal);

automatic class templates?

Is there a way to have the compile deduce the template parameter automatically?
template<class T>
struct TestA
{
TestA(T v) {}
};
template<class T>
void TestB(T v)
{
}
int main()
{
TestB (5);
}
Test B works fine, however when i change it to TestA it will not compile with the error " use of class template requires template argument list"
No, there isn't. Class templates are never deduced. The usual pattern is to have a make_ free function:
template<class T> TestA<T> make_TestA(T v)
{
return TestA<T>(v);
}
See std::pair and std::make_pair, for example.
In C++0x you will be able to do
auto someVariable = make_TestA(5);
to avoid having to specify the type for local variables.
Sunlight is right, but if I may ask you a question: is that really a problem in your code. I mean:
TestA(5);
Would become
TestA<int>(5);
As long as it's only one template argument, it's not that bad, IMHO. It's not like you can get around typing the type once in most cases.