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
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
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
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
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
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.