Consider the following case:
void Set(const std::function<void(int)> &fn);
void Set(const std::function<void(int, int)> &fn);
Now calling the function with
Set([](int a) {
//...
});
Gives "ambiguous call to overloaded function" error. I am using Visual Studio 2010. Is there a work around or another method to achieve something similar. I cannot use templates, because these functions are stored for later use because I cannot determine the number of parameters in that case. If you ask I can submit more details.
I would suggest this solution. It should work with lambdas as well as with function-objects. It can be extended to make it work for function pointer as well (just go through the link provided at the bottom)
Framework:
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
enum { arity = sizeof...(Args) };
};
template<typename Functor, size_t NArgs>
struct count_arg : std::enable_if<function_traits<Functor>::arity==NArgs, int>
{};
Usage:
template<typename Functor>
typename count_arg<Functor, 1>::type Set(Functor f)
{
std::function<void(int)> fn = f;
std::cout << "f with one argument" << std::endl;
}
template<typename Functor>
typename count_arg<Functor, 2>::type Set(Functor f)
{
std::function<void(int, int)> fn = f;
std::cout << "f with two arguments" << std::endl;
}
int main() {
Set([](int a){});
Set([](int a, int b){});
return 0;
}
Output:
f with one argument
f with two arguments
I took some help from the accepted answer of this topic:
Is it possible to figure out the parameter type and return type of a lambda?
Work around for Visual Studio 2010
Since Microsoft Visual Studio 2010 doesn't support variadic templates, then the framework-part can be implemented as:
template <typename T>
struct function_traits : public function_traits<decltype(&T::operator())>
{};
template <typename C, typename R, typename T0>
struct function_traits<R(C::*)(T0) const> { enum { arity = 1 }; };
template <typename C, typename R, typename T0, typename T1>
struct function_traits<R(C::*)(T0,T1) const> { enum { arity = 2 }; };
template <typename C, typename R, typename T0, typename T1, typename T2>
struct function_traits<R(C::*)(T0,T1,T2) const> { enum { arity = 3 }; };
//this is same as before
template<typename Functor, size_t NArgs, typename ReturnType=void>
struct count_arg : std::enable_if<function_traits<Functor>::arity==NArgs, ReturnType>
{};
EDIT
Now this code supports any return type.
I suggest:
void Set(void(*f)(int, int))
{
std::function<void(int,int)> wrap(f);
// ...
}
void Set(void(*f)(int))
{
std::function<void(int)> wrap(f);
// ...
}
You can manually specify the type:
Set(std::function<void(int)>([](int a) {
//...
}));
Related
basically how to make following code compile?
I know it failed because compiler was trying to evaluate something like ([](int &i){})(0) but how to solve the problem?
template <class TElement>
struct foo {
TElement _e;
foo(TElement e) : _e(e){}
template <class Lambda>
void bar(Lambda f) {
using TResult = decltype(std::declval<Lambda>()(std::declval<TElement>()));
}
};
int main() {
foo<int>(0).bar([](int i){}); // compile
foo<int>(0).bar([](int &&i){}); // compile
foo<int>(0).bar([](int const &i){}); // compile
foo<int>(0).bar([](int &i){}); // failed
}
You may use following traits:
template <typename T>
struct return_type : return_type<decltype(&T::operator())>
{};
// For generic types, directly use the result of the signature of its 'operator()'
template <typename ClassType, typename ReturnType, typename... Args>
struct return_type<ReturnType(ClassType::*)(Args...) const>
{
using type = ReturnType;
};
Two ways. First:
using TResult = decltype(f(_e));
or second:
using TResult = typename std::result_of<Lambda&(TElement&)>::type;
Your code implicity says that the TElement is a temprary/rvalue. The & above makes them lvalues.
You might resolve it with:
template <typename Lambda, typename T>
struct lambda_return_type {
private:
template<typename U>
static constexpr auto check(U*) -> decltype(std::declval<Lambda>()(std::declval<U>()));
template<typename U>
static constexpr auto check(...) -> decltype(std::declval<Lambda>()(std::declval<U&>()));
public:
typedef decltype(check<T>(nullptr)) type;
};
and
void bar(Lambda f) {
typedef typename lambda_return_type<Lambda, TElement>::type TResult;
}
I want to create constructors for a class in a way that the compiler trivially create new instances of it when needed.
Here's an example.
class C {
public:
C(int) {}; // int constructor
};
If I then declare a function:
void F(C _c) {};
I can call this one with an int and have the construction of C handled by the compiler:
F(0); // works
What I want to do is to achieve the same thing, but with lambdas as parameters, a few examples:
F([]() {}); //A
F([](int) {}); //B
F([](int)->int { return 0; }); //C
With SFINAE and from what I've learned from another question: Auto-constructor not working with <functional> objects
I managed to sort out a way to create a constructor that matches only a specific lambda signature, it would work out like this:
template<typename F, typename = decltype(function<void(void)>(declval<F&>()))> C(F&& f) {}; //For lambda's like A
template<typename F, typename = decltype(function<void(int)>(declval<F&>()))> C(F&& f) {}; //For lamdba's like B
template<typename F, typename = decltype(function<int(int)>(declval<F&>()))> C(F&& f) {}; //For lambda's like C
Now the problem that I have is that if I add these three definitions at once, I get an error stating that I'm trying to redefine the constructor of C. This is correct because, yeah, the constructor's being defined as C(F&& f) three times, however, how should I let know the compiler to use a different signature for each different case?
The other answer hinted me to look at enable_if and is_convertible but haven't managed to set up a workaround for this issue. Any help is greatly appreciated.
Using: Apple LLVM version 6.0 (clang-600.0.57) (based on LLVM 3.5svn)
Your current problem is that you define 3 times
template <typename F, typename> C(F&&);
but with different default argument (to do SFINAE).
You may change to
// Use to have different type easily
template <std::size_t> struct dummy {}
template<typename F, decltype(function<void(void)>(declval<F&>()), dummy<0>())* = nullptr> C(F&& f);
template<typename F, decltype(function<void(int)>(declval<F&>()), dummy<1>())* = nullptr> C(F&& f);
template<typename F, decltype(function<int(int)>(declval<F&>()), dummy<2>())* = nullptr> C(F&& f);
So you have 3 different signatures:
template<typename F, dummy<0>*> C(F&& f);
template<typename F, dummy<1>*> C(F&& f);
template<typename F, dummy<2>*> C(F&& f);
Based on top answer here, this is what I came up with. It is probably a little crude and can be improved on but the main thing it works (tried on online clang 3.5.0).
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const>
{
typedef ReturnType(signature)(Args... args);
typedef ReturnType(*ptr_signature)(Args... args);
};
class C
{
public:
template<typename F> C(F&& f) {
typedef function_traits<F> traits;
I<F>(std::move(f), reinterpret_cast<typename traits::ptr_signature>(0));
}
template<typename F> void I(F&& f, void(*)()) { std::cout << "Hello void(void) lambda" << std::endl; };
template<typename F> void I(F&& f, void(*)(int)) { std::cout << "Hello void(int) lambda" << std::endl; };
template<typename F> void I(F&& f, int(*)(int)) { std::cout << "Hello int(int) lambda" << std::endl; };
};
int main()
{
C([](int i) { return i;});
C([](int i) {});
C([]() {});
}
I have a class
template <typename T, typename W>
class A {
void foo(W);
void foo(T);
void foo(int);
}
When T=int, W=int, or W=T, this class fails to compile. How can I get the methods to take priority over each other?
I want the priority W > T > int. So if W=T, foo(T) is ignored and foo(W) is called. If T=int, foo(int) is ignored and foo(T) is called.
The compiler is VS2012, but I have Linux too, and will consider GCC/Clang solutions as well. Anything that compiles on any mainstream compiler goes, but only if you say what compilers it works on.
I would tag dispatch. Override dispatching is easy to understand and scales.
We start with a perfect forwarder:
template<class U> void foo(U&&u){
foo( std::forward<U>(u), std::is_convertible<U, W>{}, std::is_convertible<U,T>{} );
}
it creates tag types, in this case true or false types, to dispatch on.
This one:
void foo( W, std::true_type, ... );
catches everything that can convert to W.
Next, we block this one:
void foo( T, std::false_type, std::true_type );
from considerimg cases where the first argument can convert to W.
Finally, this one:
void foo( int, std::false_type, std::false_type );
can only be considered if the first parameter cannot convert to either.
Fancier tag types, or doing the dispatching one at a time, are both possible.
Sorry for typos.
I use a single C++11 feature -- {} to construct an object -- above. If your compiler lacks support for that C++11 feature, simply upgrade your compiler, it is 2014, get with it. Failing that, replace {} with ().
Use std::enable_if:
#include <type_traits>
template <typename T, typename W>
struct A {
void foo(W) {}
template<typename XT=T> typename std::enable_if<std::is_same<XT,T>::value
&& !std::is_same<T, W>::value, void>::type foo(T) {}
template<typename XT=int> typename std::enable_if<std::is_same<XT,int>::value
&& !std::is_same<int, T>::value
&& !std::is_same<int, W>::value, void>::type foo(int) {}
};
Added for testing:
template struct A<short,char>;
template struct A<char,char>;
template struct A<char,int>;
template struct A<int,char>;
template struct A<int, int>;
struct S {};
int main() {
A<S, int>{}.foo(S{});
}
For the relevant part of your template, you could use speclializations:
template <typename U, typename W>
struct Foo
{
void f(U);
void f(W);
};
template <typename T>
struct Foo<T, T>
{
void f(T);
};
For the rest of your class or class template, you can inherit from Foo<A, B> so you can keep the common code out of the part that needs to be specialized:
template <typename A, typename B>
struct TheClass : Foo<A, B>
{
// common code
};
Try template specializations:
template <typename T, typename W>
class A {
void foo(W);
void foo(T);
void foo(int);
};
template <typename T>
class A<T, T> {
void foo(T);
void foo(int);
};
template <>
class A<int, int> {
void foo(int);
};
Here is a solution without specializations of A, but with two helper structures in a few forms.
#include <iostream>
template<typename T, typename W>
struct T_type { typedef T type; };
template<typename W>
struct T_type<W, W> { typedef void* type; /*dummy type*/};
template<typename T, typename W>
struct int_type { typedef int type; };
template<typename W>
struct int_type<int, W> { typedef void** type; /*dummy type*/};
template<typename T>
struct int_type<T, int> { typedef void** type; /*dummy type*/};
template<>
struct int_type<int, int> { typedef void** type; /*dummy type*/};
template<typename T, typename W>
class A {
public:
void foo(W w) {
std::cout << "foo(W)" << std::endl;
}
void foo(typename T_type<T, W>::type t) {
std::cout << "foo(T)" << std::endl;
}
void foo(typename int_type<T, W>::type i) {
std::cout << "foo(int)" << std::endl;
}
};
int main() {
std::cout << "A<float, char>" << std::endl;
A<float, char> a;
a.foo(1.0f);
a.foo('1');
a.foo(1);
std::cout << "A<float, float>" << std::endl;
A<float, float> b;
b.foo(1.0f);
b.foo(1);
std::cout << "A<int, int>" << std::endl;
A<int, int> c;
c.foo(1);
return 0;
}
I created a template class containing a std::function as a member the following way:
template<typename Ret, typename... Args>
class Foo
{
private:
std::function<Ret(Args...)> _func;
public:
Foo(const std::function<Ret(Args...)>& func):
_func(func)
{}
};
In order not to have to specify the arguments and return type of the passed function, I created some make_foo overloads:
template<typename Ret, typename... Args>
auto make_foo(Ret (&func)(Args...))
-> Foo<Ret, Args...>
{
return { std::function<Ret(Args...)>(func) };
}
template<typename Ret, typename... Args>
auto make_foo(const std::function<Ret(Args...)>& func)
-> Foo<Ret, Args...>
{
return { func };
}
However, I was unable to create a make_foo overload that takes a lambda as parameter:
template<typename Ret, typename... Args>
auto make_foo(??? func)
-> Foo<Ret, Args...>
{
return { std::function<Ret(Args...)>(func) };
}
I just can't find a way to have the return type and argument types automatically deduced from the lambda. Is there an idiomatic way to solve such a problem?
Ok, so I thought I would die, but I finally managed to do it ç_ç
First, I used the usual indices. Since I do not have the official ones, I used old indices I wrote some months ago:
template<std::size_t...>
struct indices {};
template<std::size_t N, std::size_t... Ind>
struct make_indices:
make_indices<N-1, N-1, Ind...>
{};
template<std::size_t... Ind>
struct make_indices<0, Ind...>:
indices<Ind...>
{};
Then, I used some function traits found somewhere on StackOverflow. They are nice, and I think that they are equivalent to the Boost library linked in the comments:
template<typename T>
struct function_traits:
function_traits<decltype(&T::operator())>
{};
template<typename C, typename Ret, typename... Args>
struct function_traits<Ret(C::*)(Args...) const>
{
enum { arity = sizeof...(Args) };
using result_type = Ret;
template<std::size_t N>
using arg = typename std::tuple_element<N, std::tuple<Args...>>::type;
};
Then, I was able to write a proper make_foo function and it implementation function, since both are required to use indices. Be careful, it's plain ugly:
template<typename Function, std::size_t... Ind>
auto make_foo_(Function&& func, indices<Ind...>)
-> Foo<
typename function_traits<typename std::remove_reference<Function>::type>::result_type,
typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...>
{
using Ret = typename function_traits<typename std::remove_reference<Function>::type>::result_type;
return { std::function<Ret(typename function_traits<typename std::remove_reference<Function>::type>::template arg<Ind>...)>(func) };
}
template<typename Function, typename Indices=make_indices<function_traits<typename std::remove_reference<Function>::type>::arity>>
auto make_foo(Function&& func)
-> decltype(make_foo_(std::forward<Function>(func), Indices()))
{
return make_foo_(std::forward<Function>(func), Indices());
}
The code is somehow ugly and unreadable, but it definitely works. Hope it does not rely on some implementation-defined behaviour now. Also, thanks all for your advice, it helped! :)
int main()
{
auto lambda = [](int i, float b, long c)
{
return long(i*10+b+c);
};
auto foo = make_foo(lambda);
std::cout << foo(5, 5.0, 2) << std::endl; // 57, it works!
}
And here is the live example :)
I have an example that works with mutable lambdas. I can't quite figure out how to get the CV member qualification right.
First, here's the function template we're after:
#include <functional>
template <typename R, typename ...Args>
void foo(std::function<R(Args...)> f)
{ }
Now we'll let a function template bar take an arbitrary lambda and call the right version of foo, by inspecting the type of the lambda's operator():
#include <type_traits>
template <typename> struct remove_member;
template <typename C, typename T>
struct remove_member<T C::*>
{ using type = T; };
template <typename F>
void bar(F f)
{
using ft = decltype(&F::operator());
foo(std::function<typename remove_member<ft>::type>(f));
}
Example:
int q;
bar([&](int a, int b) mutable -> int { q = a + b; return q / b; });
You can use normal, const lambdas with this modified trait, though I don't like having to spell the function type out:
template <typename C, typename R, typename ...Args>
struct remove_member<R (C::*)(Args...) const>
{ using type = R(Args...); };
I thought it might work with the original code if I use typename std::remove_cv<T>::type, but at least on GCC this doesn't work because of some strange __attribute__((const)) that's set on the lambda's operator type which seems to interfere with the template specialization.
Question is simple, how would I implement a function taking a variable number of arguments (alike the variadic template), however where all arguments have the same type, say int.
I was thinking about something alike this;
void func(int... Arguments)
Alternatively wont a recursive static assert on the types work?
A possible solution is to make the parameter type a container that can be initialized by a brace initializer list, such as std::initializer_list<int> or std::vector<int>. For example:
#include <iostream>
#include <initializer_list>
void func(std::initializer_list<int> a_args)
{
for (auto i: a_args) std::cout << i << '\n';
}
int main()
{
func({4, 7});
func({4, 7, 12, 14});
}
Here's a version that removes the function from the overload set, instead of giving a static_assert. This is allows you to provide other overloads of the function that could be used when the types aren't all the same, rather than a fatal static_assert that can't be avoided.
#include <type_traits>
template<typename... T>
struct all_same : std::false_type { };
template<>
struct all_same<> : std::true_type { };
template<typename T>
struct all_same<T> : std::true_type { };
template<typename T, typename... Ts>
struct all_same<T, T, Ts...> : all_same<T, Ts...> { };
template<typename... T>
typename std::enable_if<all_same<T...>::value, void>::type
func(T...)
{ }
If you want to support perfect forwarding you probably want to decay the types before checking them, so that the function will accept a mix of lvalue and rvalue arguments as long as they have the same type:
template<typename... T>
typename std::enable_if<all_same<typename std::decay<T>::type...>::value, void>::type
func(T&&...)
{ }
Alternatively, if you have a general purpose trait for testing the logical conjunction you can do it using std::is_same instead of writing your own all_same:
template<typename T, typename... Ts>
typename std::enable_if<and_<is_same<T, Ts>...>::value, void>::type
func(T&&, Ts&&...)
{ }
Because this requires at least one argument you'd also need another overload to support the zero-argument case:
void func() { }
The and_ helper can be defined like so:
template<typename...>
struct and_;
template<>
struct and_<>
: public std::true_type
{ };
template<typename B1>
struct and_<B1>
: public B1
{ };
template<typename B1, typename B2>
struct and_<B1, B2>
: public std::conditional<B1::value, B2, B1>::type
{ };
template<typename B1, typename B2, typename B3, typename... Bn>
struct and_<B1, B2, B3, Bn...>
: public std::conditional<B1::value, and_<B2, B3, Bn...>, B1>::type
{ };
I think you can do this by specifying a concrete type when chewing your arguments out of the argument pack. Something like:
class MyClass{};
class MyOtherClass{};
void func()
{
// do something
}
template< typename... Arguments >
void func( MyClass arg, Arguments ... args )
{
// do something with arg
func( args... );
// do something more with arg
}
void main()
{
MyClass a, b, c;
MyOtherClass d;
int i;
float f;
func( a, b, c ); // compiles fine
func( i, f, d ); // cannot convert
}
In the generic case void func( MyClass arg, Arguments ... args ) would become void func( arg, Arguments ... args ) with a template type T.
#Skeen
How about this?
template <typename T>
void func_1(std::initializer_list<T>&& a) {
// do something
}
template <typename... T>
void func(T&&... a) {
func_1({std::forward<T>(a)...});
}
int main() {
func(1, 2, 3);
// func(1, 2, 3, 4.0); // OK doesn't compile
}
If you don't want to use brace-based initializer_list/vector and want to keep the arguments separate in form of argument pack, then below solution checks it at compile time using recursive static_asserts:
#include<type_traits>
template<typename T1, typename T2, typename... Error>
struct is_same : std::false_type {};
template<typename T, typename... Checking>
struct is_same<T, T, Checking...> : is_same<T, Checking...> {};
template<typename T>
struct is_same<T,T> : std::true_type {};
template<typename... LeftMost>
void func (LeftMost&&... args)
{
static_assert(is_same<typename std::decay<LeftMost>::type...>::value,
"All types are not same as 'LeftMost'");
// ...
}
int main ()
{
int var = 2;
func(1,var,3,4,5); // ok
func(1,2,3,4.0,5); // error due to `static_assert` failure
}
Actually this solution would check all the arguments with respect to the first argument. Suppose it was double then everything would be checked against double.
Because I don't think I saw this solution, you could write a specific function for every type (in your case, just int) then a forwarding function taking variadic argument types.
Write each specific case:
then for each specific case:
// only int in your case
void func(int i){
std::cout << "int i = " << i << std::endl;
}
Then your forwarding function like this:
template<typename Arg0, typename Arg1 typename ... Args>
void func(Arg0 &&arg0, Arg1 &&arg1, Args &&... args){
func(std::forward<Arg0>(arg0));
func(std::forward<Arg1>(arg1), std::forward<Args>(args)...);
}
This is good because it is expandable for when you want to accept maybe another type too.
Used like this:
int main(){
func(1, 2, 3, 4); // works fine
func(1.0f, 2.0f, 3.0f, 4.0f); // compile error, no func(float)
}