could not deduce template argument in VS 2010 - c++

In VS 2005 this code work fine, but in VS 2010 I have error
"could not deduce template argument for 'T *' from 'std::queue<_Ty> *'"
I can't understand what the problem is? Please, help me...
#include <string>
#include <queue>
using namespace std;
template<typename T, typename R, typename P1>
int bindthis(T* obj, R (T::*func)(P1))
{
return 1;
}
int _tmain(int argc, _TCHAR* argv[])
{
std::queue<std::wstring> queue_;
bindthis(&queue_, &std::queue<std::wstring>::push);
return 0;
}

I'm not sure about Visual Studio, but in GCC this function compiles in C++03 mode but not in C++11 mode, so I imagine the problem is the same.
The issue is that in C++11, an overload was added to std::queue::push, so the compiler doesn't know which overload to pick. There are two ways to fix this:
Specify the template arguments explicitly:
bindthis<std::queue<std::wstring>, void, const std::wstring&>(&queue_, &std::queue<std::wstring>::push);
Cast the function pointer to the desired type void (std::queue<std::wstring>::*)(const std::wstring&), so that the correct overload is chosen:
typedef void (std::queue<std::wstring>::*push_func_ptr)(const std::wstring&);
bindthis(&queue_, static_cast<push_func_ptr>(&std::queue<std::wstring>::push));

Related

Class template argument deduction fails leads to substitution failure

I have a simple program that I am attempting to use to test C++17's class template argument deduction.
#include <iostream>
#include <list>
int main(int argc, const char * argv[]) {
const char* a = "Hello";
std::list x(1, a);
return 0;
}
I would like to std::list to deduce the list having type const char*. However when attempting to run this code I obtain the error No viable constructor or deduction guide for deduction of template arguments of 'list'. Specifically the constructor that should be matched to this list(size_type __n, const value_type& __x); reports an error saying:
Candidate template ignored: substitution failure [with _Tp = const char *, _Alloc = std::__1::allocator<const char *>]: 'size_type' is a protected member of 'std::__1::__list_imp<const char *, std::__1::allocator<const char *> >'
I am curious why this does not work and yet a program like this is completely well formed with std::pair able to easily deduce the arguments:
#include <iostream>
#include <list>
int main(int argc, const char * argv[]) {
const char* a = "Hello";
std::pair x(1, a);
return 0;
}
Thank you.
clang 5 and 6 and gcc 7 and 8 compile your code without problem. So you are using either a compiler that didn't implement correctly the deduction guides or a library that doesn't have the appropriate deduction guides for std::list

VS2015 with VC++ 2008 toolset template deduction failure

Sample code to reproduce the problem:
#include <iostream>
template< typename T, typename Func >
void action(Func T::* func)
{
T entry;
(entry.*func)();
}
struct A
{
void f()
{
std::cout << "A::f()" << std::endl;
}
};
int main()
{
action(&A::f);
return 0;
}
This code successfully compiles using MS VC++2008, with VC++2015 using vc140 toolset, but fails to compile when used in VC++2015 project with vc90 (VC++2008) toolset. Gives strange diagnostics of
cpptest.cpp(20): error C2664: 'action' : cannot convert parameter 1 from 'void (__thiscall A::* )(void)' to 'void (A::* )(void)'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Seems compiler looses __thiscall calling convention specifier when deducing type for Func. Tried to forcibly specify __thiscall in different parts of the code but had no success. Converting the whole project to vc14 toolset is not a way because of various dependencies and keeping it under the VS 2008 is an unlikely way. Any ideas to force compiler to understand such a construction?
Update
Changing code to
template< typename T, typename Func >
void action(Func func)
....
and calling to action< A >( &A::f ); works, but looks little ugly - I expect compiler to be able to deduce type for both template arguments (T and Func) automatically

Partial deduction of template arguments in VS2013 for variadic template

The following fails to deduce template arguments in VS2013 with the following error,error C2440: 'initializing' : cannot convert from 'overloaded-function' to 'f'. However compiles fine GCC.
template <class TRAIT, class ...T>
void myVarFunc(T...arg)
{
printf("test");
}
typedef void(*f)(int a, char b);
int main(int argc, char* argv[])
{
f myf = &myVarFunc<int>;
myf(1, 'x');
return 0;
}
Can anyone determine why this fails, the same function can be instantiated using the following:
myVarFunc<int>(1, 'x'); //compiles ok
And the following also compiles:
template <class ...Args>
void myVarFunc(Args...arg)
{
printf("test");
}
typedef void(*f)(int a, char b);
int main(int argc, char* argv[])
{
f myf = myVarFunc; //compiles ok
myf(1, 'x');
return 0;
}
So when adding an extra type to the template, it fails to deduce the parameters, could this be a compiler bug, or just not supported by the language?
Thanks

Boost Fusion compile error in VS 2013 RC

Hello I got the latest Boost from trunk which builds with VS 2013 RC. Built boost, it worked.
But when compiling my project against Boost, where I make use of Boost Fusion. I'm getting 100's of these error messages--
Error 1086 error C3520: 'T' : parameter pack must be expanded in this context
It refers to this code in make_vector10.hpp
namespace result_of
{
template <typename T0 , typename T1 , typename T2>
struct make_vector<T0 , T1 , T2>
{
typedef vector3<typename detail::as_fusion_element<T0>::type , typename detail::as_fusion_element<T1>::type , typename detail::as_fusion_element<T2>::type> type;
};
}
But there is no template parameter "T" used anywhere here.
This is also not a variadic template so I don't understand why it refers to parameter packs in the error message. "vector3" and "as_fusion_element" are also not variadic.
All variations of make_vector are giving me the same error btw(also make_set).
Anyone know what is going on here? Thanks
Here is a minimal repro
#include <boost/fusion/container.hpp>
#include <boost/fusion/algorithm.hpp>
#include <boost/fusion/include/algorithm.hpp>
#include <boost/fusion/sequence.hpp>
#include <boost/fusion/include/sequence.hpp>
#include <boost/fusion/support/pair.hpp>
#include <boost/fusion/include/pair.hpp>
namespace fs = boost::fusion;
namespace Key {
struct prep_table{}; struct draw_single{};
};
int main() {
fs::map<std::pair<Key::prep_table, float>, std::pair<Key::draw_single, int>> Blah;
return 0;
}
It was a compiler bug as reported by Felix Petroconi in the comments.
Work around: get latest boost, but roll back fusion to an earlier version

Clang " couldn't infer template argument " whereas gcc / g++ can. Which is right?

I have been trying to compile a project (which is fine using gcc/g++) with clang and compilation stuck on a template invocation.
I've tried to create the simplest similar piece of code exhibiting the same error message. Here it is:
#include <vector>
#include <utility>
#include <iostream>
using namespace std;
int A( double in )
{
return 1;
}
int A( int in )
{
return 1;
}
template<class M, class T>
M test(T input, M (fun) (T) )
{
return fun( input );
}
int main( int argc, const char *argv[] )
{
cout << test( (int) 1, A ) << test( (double) 1.2, A ) << endl;
return 0;
}
The error from clang (appears twice of course):
error: no matching function for call to 'test'
candidate template ignored: couldn't infer template argument 'M'
Gcc doesn't complain.
Please note M is the return type and is always "int".
Does someone know which is right and why?
Thanks
g++ is wrong. From C++11 [temp.deduct.type]p5:
The non-deduced contexts are: [...]
- A function parameter for which argument deduction cannot be done because the associated function argument is [...] a set of overloaded functions, and [...] more than one function matches the function parameter type
This determination is made without regard to template parameters that might have been deduced elsewhere, so the fact that T must deduce as int is not relevant here. This makes the entire parameter M (fun)(T) a non-deduced context. Therefore M cannot be deduced, just as Clang claims.
g++ appears to incorrectly be using the 'T = int' deduction from the first function parameter when determining whether the second parameter is a non-deduced context. Reversing the order of the function parameters causes g++ to reject the code too:
int A(double);
int A(int);
template<class M, class T>
M test(M (fun) (T), T input) {
return fun( input );
}
int main( int argc, const char *argv[]) {
test(A, 1);
test(A, 1.2);
}
My previous answer (now deleted) was wrong. Clang is wrong.
The compiler should be able to deduce the type M because the function argument is M(fun)(T). Note that there is no M in the function pointer argument list, so this corresponds to the T() (C++11) / T(*)() (C++93) in 14.8.2.5:
where (T) represents a parameter-type-list where at least one parameter type contains a T, and () represents a parameter-type-list where no parameter type contains a T.