error C2783 Could not deduce template arguments - c++

I am stuck with this error . I have found a workaround too but it kind of kills the whole purpose of exercise.
I am trying to create a function which will take two iterators pointing to same container . I will find the sum of elements between them. I created general function for the sequential containers like vector which works fine. I overloaded the same function for associative containers. This is the one giving error.
map<string,double> myMap;
myMap["B"]=1.0;
myMap["C"]=2.0;
myMap["S"]=3.0;
myMap["G"]=4.0;
myMap["P"]=5.0;
map<string,double>::const_iterator iter1=myMap.begin();
map<string,double>::const_iterator iter2=myMap.end();
cout<<"\nSum of map using the iterator specified range is: "<<Sum(iter1,iter2)<<"\n";
//Above line giving error. Intellisense is saying: Sum, Error: no instance of overloaded function "Sum" matches the argument list.
//function to calculate the sum is listed below (It appears in a header file with <map> header included):
template <typename T1,typename T2>
double Sum(const typename std::map<T1,T2>::const_iterator& input_begin,const typename std::map<T1,T2>::const_iterator& input_end)
{
double finalSum=0;
typename std::map<T1,T2>::const_iterator iter=input_begin;
for(iter; iter!=input_end; ++iter)
{
finalSum=finalSum+ (iter)->second;
}
return finalSum;
}
Compilation error is:
1>c:\documents and settings\ABC\my documents\visual studio 2010\projects\demo.cpp(41): error C2783: 'double Sum(const std::map::const_iterator &,const std::map::const_iterator &)' : could not deduce template argument for 'T1'
Workaround:
If call Sum(iter1,iter2) is replaced with Sum < string,double > (iter1,iter2), it compiles fine.
Was I trying to do something impossible as per C++ standards in the first place?

The error is actually quite clear, in the following template:
template <typename T1,typename T2>
double Sum(const typename std::map<T1,T2>::const_iterator& input_begin,
const typename std::map<T1,T2>::const_iterator& input_end)
The types T1 and T2 cannot be deduced from the argument at the place of call. This is defined as such in the standard and if you think about it (in the general case) it makes sense.
Consider that instead of std::map<>::const_iterator you had sometemplate<T>::nested_type and that the argument at the place of call was an int. If the compiler had to deduce the type, it would have to instantiate sometemplate for all possible types T in the universe (infinite set) and find for which of them the nested type nested_type is a typedef to int.
As someone points out in the comments you can change the template so that instead of being templated on the key and value types of the map it just takes the iterators.
Delegating extraction of the value
This is a workaround to providing a single implementation of Sum that can deal with both sequential and associative containers.
namespace detail {
template <typename T> T valueOf( T const & t ) { return t; }
template <typename K, typename V>
V valueOf( std::pair<const K, V> const & p ) {
return p.second;
}
}
template <typename Iterator>
double Sum( Iterator begin, Iterator end ) {
double result = 0;
for (; begin != end; ++begin) {
result += detail::valueOf(*begin);
}
return result;
}
I have not tested the code, but that should do it. And this is probably much simpler than using SFINAE on the Sum template.

Related

Can type arguments be made deduceable for function templates using std container?

I found this implementation of a few common features of functional programming, e.g. map / reduce:
(I'm aware stuff like that is aparently coming or partially present in new C++ versions)
github link
A part of the code:
template <typename T, typename U>
U foldLeft(const std::vector<T>& data,
const U& initialValue,
const std::function<U(U,T)>& foldFn) {
typedef typename std::vector<T>::const_iterator Iterator;
U accumulator = initialValue;
Iterator end = data.cend();
for (Iterator it = data.cbegin(); it != end; ++it) {
accumulator = foldFn(accumulator, *it);
}
return accumulator;
}
template <typename T, typename U>
std::vector<U> map(const std::vector<T>& data, const std::function<U(T)> mapper) {
std::vector<U> result;
foldLeft<T, std::vector<U>&>(data, result, [mapper] (std::vector<U>& res, T value) -> std::vector<U>& {
res.push_back(mapper(value));
return res;
});
return result;
}
Usage example:
std::vector<int> biggerInts = map<int,int>(test, [] (int num) { return num + 10; });
The type arguments T,U have to be fully qualified for this to compile, as shown in the example, with e.g. map< int,int >( ... ).
This implementation is for C++11, as mentioned on the linked-to page.
Is it possible with newer C++ versions (or even 11) now to make the use of this less verbose, i.e. making the types U,T deduce automatically?
I have googled for that and only found that there is apparently some improvement for class template, as opposed to function template, argument deduction in C++17.
But since I only ever used templates in a rather basic manner, I was wondering whether there is something in existence that I'm not aware of which could improve this implementation verboseness-wise.
You can rewrite map signature to be:
template <typename T, typename M, typename U = decltype(std::declval<M>()(T{}))>
std::vector<U> map(const std::vector<T>& data, const M mapper)
then T will be deduced as value_type of vector's items.
M is any callable object.
U is deduced as return type of M() functor when called for T{}.
Below
std::vector<int> biggerInts = map(test, [] (int num) { return num + 10; });
^^^^ empty template arguments list
works fine.
Live demo
More general templates make template argument deduction easier.
One principle: it is often a mistake to use a std::function as a templated function's parameter. std::function is a type erasure, for use when something needs to store some unknown invokable thing as a specific type. But templates already have the ability to handle any arbitrary invokable type. So if we just use a generic typename FuncT template parameter, it can be deduced for a raw pointer-to-function, a lambda, or another class with operator() directly.
We might as well also get more general and accept any input container instead of just vector, then determine T from it, if it's even directly needed.
So for C++11 I would rewrite these:
// C++20 is adding std::remove_cvref, but it's trivial to implement:
template <typename T>
using remove_cvref_t =
typename std::remove_cv<typename std::remove_reference<T>::type>::type;
template <typename Container, typename U, typename FuncT>
remove_cvref_t<U> foldLeft(
const Container& data,
U&& initialValue,
const FuncT& foldFn) {
remove_cvref_t<U> accumulator = std::forward<U>(initialValue);
for (const auto& elem : data) {
accumulator = foldFn(std::move(accumulator), elem);
}
return accumulator;
}
template <typename Container, typename FuncT>
auto map(const Container& data, const FuncT& mapper)
-> std::vector<remove_cvref_t<decltype(mapper(*std::begin(data)))>>
{
using T = remove_cvref_t<decltype(*std::begin(data))>;
using ResultT = std::vector<remove_cvref_t<decltype(mapper(std::declval<const T&>()))>>;
ResultT result;
foldLeft(data, std::ref(result), [&mapper] (ResultT &res, const T& value) -> ResultT& {
res.push_back(mapper(value));
return res;
});
return result;
}
See the working program on coliru.
There was one unfortunate thing about the old map: it potentially copied the result vector at every iteration. The = in accumulator = foldFn(accumulator, *it); is a self-assignment, which might do nothing, or might allocate new memory, copy contents, then free the old memory and update the container. So instead I've changed the U for foldLeft in this case to a std::reference_wrapper. The = in that case will still "rebind" the wrapper to the same object, but that will at least be quick.
In C++14 and later, you could do away with finding T within map by using a generic lambda: [&mapper] (std::vector<U>& res, const auto& value) ...

How do I use nested templates in c++?

I am new to C++ and doing a class in it now. As homework, we are supposed to write a function that accepts any container as input but does not use iterators. So we are not allowed to just pass std::begin(container) and std::end(container) as arguments. We have to pass the containers as references. My take on this was the following function declaration:
template <typename T, typename U, typename V, template <typename a, typename b> typename container>
void doStuff(container<T, U>& first, container<T, V>& second)
{
// the code
}
It accepts two containers (or any templated type that uses two template arguments). The second template argument in container is different since in arrays V might represent the size of the array and I want to be able to accept two arrays of different sizes.
Example:
std::array<bool, 4> a1 = { true, false, false, false };
std::array<bool, 1> a2 = { false };
Unfortunately, this example does not work. The error says that I doStuff does not accept arguments of these types. Why is that?
In my opinion, using a "templated template" here is important, because I would like to make sure that the function only accepts two containers if they contain the same kind of data. So passing an int array and a double array should not work.
If you want to support as many container types as possible, you should use the least restricting definition possible:
template <typename FirstContainer, typename SecondContainer>
void doStuff(FirstContainer& first, SecondContainer& second)
{
}
This is because container types come in all sort of flavors, e.g. std::array is a template taking a value type and a static size as argument, std::vector is a template taking a value type and an allocator, some custom StringList might not be a template at all.
Your implementation might have some specific requirements to the supported containers, e.g. it might only work for containers of integer types. But more often than not this is just an implicit result of the implementation. Take for a example a simple function summing up values of two containers:
template <typename FirstContainer, typename SecondContainer>
int sum(const FirstContainer& first, const SecondContainer& second)
{
int result = 0;
for (auto value : first)
result += value;
for (auto value : second)
result += value;
return result;
}
This function works fine with any value types that can be added to an integer. If it can't be added (like a std::string), it will cause a compilation error eventually.
(Note that one could write this function even more generic with an automatically deduced sum type instead of just int)
If these "implicit requirements" are not enough for you, you can add explicit checks using static_assert:
template <typename FirstContainer, typename SecondContainer>
int sum(const FirstContainer& first, const SecondContainer& second)
{
int result = 0;
for (auto value : first)
{
static_assert(std::is_same_v<int, decltype(value)>, "FirstContainer does not hold integers");
result += value;
}
for (auto value : second)
{
static_assert(std::is_same_v<int, decltype(value)>, "SecondContainer does not hold integers");
result += value;
}
return result;
}
Now your function is only accepting containers holding plain int, nothing else.
You can also use std::enable_if to completely "disable" your function for non-supported containers:
template <typename FirstContainer, typename SecondContainer>
auto sum(const FirstContainer& first, const SecondContainer& second)
-> std::enable_if_t<
std::is_same_v<typename FirstContainer::value_type, int> &&
std::is_same_v<typename SecondContainer::value_type, int>,
int
>
{
int result = 0;
for (auto value : first)
result += value;
for (auto value : second)
result += value;
return result;
}
Now your function is restricted to containers with a nested typedef value_type to type int.

template argument type deduction from std::function return type with lambda

First of, I'm using C++11 (and my topic sucks).
What I'm trying to do is write a generic template function that implements something usually called sort_by in other programming languages. It involves calculating an arbitrary criterion for each member of a range exactly once and then sorting that range according to those criteria. Such a criterion doesn't have to be a POD, all it has to be is less-than-comparable. For things for which std::less doesn't work the caller should be able to provide her own comparison functor.
I've successfully written said function which uses the following signature:
template< typename Tcriterion
, typename Titer
, typename Tcompare = std::less<Tcriterion>
>
void
sort_by(Titer first, Titer last,
std::function<Tcriterion(typename std::iterator_traits<Titer>::value_type const &)> criterion_maker,
Tcompare comparator = Tcompare()) {
}
It can be used e.g. like this:
struct S { int a; std::string b; double c; };
std::vector<S> s_vec{
{ 42, "hello", 0.5 },
{ 42, "moo!", 1.2 },
{ 23, "fubar", 0.2 },
};
sort_by1< std::pair<int, double> >(
s_vec.begin(), s_vec.end(),
[](S const &one_s) { return std::make_pair(one_s.a, one_s.c); }
);
What I don't like about this approach is that I have to provide the Tcriterion argument myself because the compiler cannot deduce that type from the lambda expression. Therefore this does not work:
sort_by1(s_vec.begin(), s_vec.end(), [](S const &one_s) { return std::make_pair(one_s.a, one_s.c); });
clang 3.1 and gcc 4.7.1 both bark on this (gcc 4.7.1 even barks on the code above, so I guess I'm really doing something wrong here).
However, if I assign the lambda to a std::function first then at least clang 3.1 can deduce the argument, meaning this works:
typedef std::pair<int, double> criterion_type;
std::function<criterion_type(S const &)> criterion_maker = [](S const &one_s) {
return std::make_pair(one_s.a, one_s.c);
};
sort_by1(s_vec.begin(), s_vec.end(), criterion_maker);
So my questions are: How do I have to change my function signature so that I don't need to specify that one argument? And (probably related) how would I fix my example to have it working with gcc?
Don't use std::function in tandem with template argument deduction. In fact, there's very likely no reason to use std::function in a function or function template argument list. More often than not, you should not use std::function; it is a very specialized tool that is very good at solving one particular problem. The rest of the time, you can dispense with it altogether.
In your case you don't need template argument deduction if you use a polymorphic functor to order things:
struct less {
template<typename T, typename U>
auto operator()(T&& t, U&& u) const
-> decltype( std::declval<T>() < std::declval<U>() )
{ return std::forward<T>(t) < std::forward<U>(u); }
// operator< is not appropriate for pointers however
// the Standard defines a 'composite pointer type' that
// would be very helpful here, left as an exercise to implement
template<typename T, typename U>
bool operator()(T* t, U* u) const
{ return std::less<typename std::common_type<T*, U*>::type> {}(t, u); }
};
You can then declare:
template<typename Iter, typename Criterion, typename Comparator = less>
void sort_by(Iter first, Iter last, Criterion crit, Comparator comp = less {});
and comp(*ita, *itb) will do the right thing, as well as comp(crit(*ita), crit(*itb)) or anything else as long as it makes sense.
How about something like this:
template< typename Titer
, typename Tmaker
, typename Tcompare
>
void
sort_by(Titer first, Titer last,
Tmaker criterion_maker,
Tcompare comparator)
{
typedef decltype(criterion_maker(*first)) Tcriterion;
/*
Now that you know the actual type of your criterion,
you can do the real work here
*/
}
The problem is that you can obviously not use a default for the comparator with this, but you can easily overcome that by providing an overload that doesn't take a comparator and fills in std::less internally.
To do it like you originally suggested, the compiler would have to be able to "invert" the template instantiation process. I.e. for a given std::function<> instantiation, what parameter do I have to supply as the result to get it. This "looks" easy, but it is not!
You can use also something like this.
template< typename Titer
, typename Tmaker
, typename TCriterion = typename
std::result_of
<
Tmaker
(
decltype(*std::declval<Titer>())
)
>::type
, typename Tcompare = std::less<TCriterion>
>
void
sort_by(Titer first, Titer last,
Tmaker criterion_maker, Tcompare comparator = Tcompare())
{
}
http://liveworkspace.org/code/0aacc8906ab4102ac62ef0e45a37707d

template constructor and typedef iterator

I want to define a constructor working with any constructor having begin, end, operator++.
In other words I want to get this behavior (commented, working code):
/*Polyn(std::vector<double> &a) : CalcDerivative(0) , CalcIntegral(0) {
for(std::vector<double>::iterator i = a.begin();i < a.end();++i)
params.push_back(*i);
}*/
with other iterators. (for instance lists too).
template <typename T>
Polyn(const T &a) : CalcDerivative(0) , CalcIntegral(0) {
typename std::vector<T>::iterator iter;
for(iter i = a.begin();i < a.end();++i) //LINEA 18!!
params.push_back(*i);
}
What I get is this compilation error:
polyn.h: In constructor ‘Polyn::Polyn(const T&)’:
polyn.h:18: error: expected ‘;’ before ‘i’
why? How to fix my code?
First of all, the parameter type of the function should be std::vector<T> const & rather than T const &. And then you should use const_iterator:
typename std::vector<T>::const_iterator iter;
Because vector a is a const object.
Even better if you implement the constructor as:
template <typename T>
Polyn(const std::vector<T> &a)
: params(a.begin(), a.end()), CalcDerivative(0) , CalcIntegral(0)
{
}
That is, initialize params in the member-initialization-list itself.
In addition to Nawaz's answer, if you want to support any container type supporting begin, end and a forward iterator, you may want to use:
template <typename C>
Polyn(const C &a)
: params(a.begin(), a.end()), CalcDerivative(0) , CalcIntegral(0)
{
}
This way it also works for std::lists and std::maps and whatever. Or, when having C++11 support, you should actually use the even more general std::begin(a) and std::end(a), so it will even work for plain arrays or anything else specializing std::begin and std::end.
Another option, which is a bit more STL-like, would be to directly use iterators as arguments, but then you have to do the begin/end manually in the client code (when calling the constructor):
template <typename InputIterator>
Polyn(const InputIterator &b, const InputIterator &e)
: params(b, e), CalcDerivative(0) , CalcIntegral(0)
{
}

Way to determine proper predicate for templated types

Suppose I have a function which looks like this:
template <class In, class In2>
void func(In first, In last, In2 first2);
I would like this function to call another function which accepts a predicate. My initial instinct was to do something like this:
template <class In, class In2>
void func(In first, In last, In2 first2) {
typedef typename std::iterator_traits<In>::value_type T;
other_func(first, last, first2, std::less<T>());
}
But there is a problem, what if In and In2 are iterators to different types? For example, char* vs int*. Depending on which is In and which is In2 the predicate may be truncating values during its comparison. For example, if In is char* then std::less<char> will be called even if In2 is an int*.
When ::operator< is given two parameters, the compiler is able to deduce the correct type and the standard type promotion rules apply. However, when selecting a predicate to pass to a function, there is no oportunity to have this happen. Is there some clever way to figure out which version of std::less<> I want to pass based on In and In2?
EDIT:
The following example illustrates the problem:
unsigned int x = 0x80000000;
unsigned char y = 1;
std::cout << std::less<unsigned char>()(x, y) << std::endl;
std::cout << std::less<unsigned int>()(x, y) << std::endl;
will output:
1
0
EDIT:
After thinking about it, what I would really like is to be able to do something like this:
typedef typeof(T1() < T2()) T;
other_func(first, last, first2, std::less<T>());
I suppose I could use gcc's __typeof__ extension..., but I don't love that idea either. Any way to get that net effect in a standard conformant way?
I seemed to remember that there was a traits for this in boost, but I can't find it after a quick search. If you are no more successful than me, you can construct it yourself,
template <typename T1, typename T2>
struct least_common_promotion;
template <>
struct least_common_promotion<short, int>
{
typedef int type;
};
but you'll have to specify quite a few explicit specializations. The type traits library of boost can perhaps help you reduce their number.
Edit: I feel stupid, such kind of things are needed for operation (where the result type depend on the operands types), but not for predicates (where the result type is bool). You can simply write:
template <class T1, T2>
struct unhomogenous_less : public std::binary_function<T1, T2, bool>
{
bool operator()(T1 const& l, T2 const& r) const
{ return l < r; }
};
...
typedef typename std::iterator_traits<In>::value_type value_type_1;
typedef typename std::iterator_traits<In2>::value_type value_type_2;
other_func(first, last, first2, unhomogenous_less<value_type_1, value_type_2>());
If your requirements on the algorithm are such that In's value_type need not be the same as In2's value type, then I would leave the template parameters as you have them; otherwise they should be the same.
Whether they are the same or different it is up to the client of your routine to meet the prerequisites of the algorithm, which you are allowed to specify. For example, here you could require that the value_type of In be the same as the value_type of In2. If that holds true, then, the function should compile and be correct as the client expects.
In such a case, then, you can pass a std::less<T> instance of the value_type of either template type, and you should be fine.
However, if the client violates that precondition (as in the example you provide above where char is not the same as int), then it will be up to the client, not you, to correct the compile-time error.
Make sure your algorithm is well-documented, to say the least :)
Taking SGI's old implementation of std::equal as an example, STL algorithms handle this kind of situation by having two versions of the same algorithm: one that uses the intrinsic < operator which the compiler deduces at compile time, and one that takes a user-defined binary predicate so the user can use any types they'd prefer:
template <class _InputIter1, class _InputIter2>
inline bool equal(_InputIter1 __first1, _InputIter1 __last1,
_InputIter2 __first2) {
__STL_REQUIRES(_InputIter1, _InputIterator);
__STL_REQUIRES(_InputIter2, _InputIterator);
__STL_REQUIRES(typename iterator_traits<_InputIter1>::value_type,
_EqualityComparable);
__STL_REQUIRES(typename iterator_traits<_InputIter2>::value_type,
_EqualityComparable);
for ( ; __first1 != __last1; ++__first1, ++__first2)
if (*__first1 != *__first2)
return false;
return true;
}
template <class _InputIter1, class _InputIter2, class _BinaryPredicate>
inline bool equal(_InputIter1 __first1, _InputIter1 __last1,
_InputIter2 __first2, _BinaryPredicate __binary_pred) {
__STL_REQUIRES(_InputIter1, _InputIterator);
__STL_REQUIRES(_InputIter2, _InputIterator);
for ( ; __first1 != __last1; ++__first1, ++__first2)
if (!__binary_pred(*__first1, *__first2))
return false;
return true;
}
(Note: Old SGI STL code taken from here.)