Suppose I have the following definitions:
int f(int ) { return 1; } // a)
template<typename T> int f(T x) { return 2; } // b)
I understand that if I call f, e.g. f(1), the non-template overload a) will be preferred, but is there a way to unambiguously refer to a)? For instance, I can use f<int> to refer to b) unambiguously.
As an example of why this would be useful, consider the following function:
template<typename Func, typename T> void print_result(Func f, T arg)
{
std::cout << f(arg) << std::endl;
}
If I try to use it on f, e.g, print_result(f,1), I get a compilation error (the compiler does not know which f I mean). I can use print_result(f<int>,1) to tell it to use b), but how do I tell it to use a) ?
I found I can use print_result(static_cast<int (*)(int)>(f), 1), but this feels hacky and is cumbersome. Is there a better way?
use template specialization:
template<>
int f<int>(int x ) { return 1; } // a)
Related
I have this code:
struct Foo{
int sum;
Foo() : sum(0) {}
Foo(int x) : sum(x) {}
Foo bar(int x){
return Foo(sum + 1);
}
Foo bar(std::vector<int> x){
return Foo(sum + 1);
}
Foo bar(const char* str){
return Foo(sum + 1);
}
};
template <typename ... T>
int foo(T ... args){
Foo foo;
//(foo.bar(args), ...);
return foo.sum;
}
int main() {
foo(1, 2, "hello", std::vector<int>());
return 0;
}
I want to create the call hierarchy like this:
Foo foo;
foo = foo.bar(1);
foo = foo.bar(2);
foo = foo.bar("hello");
based on variadic templated arguments args.
I was looking at fold expressions, but that seems to be not working as I need. I can fold methods to be called separatelly, but cannot call the next one on the result from the previous one.
Is there any way how to do this with?
You can use a folding expression for that.
((foo = foo.bar(args)), ...);
We need an additional () around the assignement to make the compiler accept the syntax.
I'm assuming this is what you want? I can't really tell what the code is supposed to do...
Edit:
As pointer out by #AVH doing a left-fold or right-fold here will have an impact on the order. The right-fold above will call the member functions starting with the last parameter and work it's way backward. A left-fold is probably what you want, and will do the opposite.
(..., (foo = foo.bar(args)));
Edit 2:
In the end it turns out that the comma operator enforces evaluation from left to right, so in this case it actually does not matter how we fold the expression. If we folded over something other then , it could matter.
Here is a generic for for-each-in-pack function:
template<class F, class...Args>
constexpr F for_each(F f, Args&&...args) {
std::initializer_list<int>{((void)f(std::forward<Args>(args)), 0)...};
return f;
}
It's taken from here. Use that together with a lambda:
template <typename ... T>
int foo(T&& ... args){
Foo foo;
for_each([&](auto&& x){ foo = foo.bar(std::forward<decltype(x)>(x));}
, std::forward<T>(args) ...>);
return foo.sum;
}
That's basically the same solution as the accepted one, but with the function abstracted.
I'm trying to create a function template which accepts std::max and others with compatible prototypes:
template <typename F>
int f(F g)
{
return g(1,2);
}
Because of the many overloads, the template argument F cannot be inferred f.e. for std::max, so this will fail:
f(std::max);
One possibility is to hint with a static_cast:
f(static_cast<int const& (*)(int const&,int const&)>(std::max));
I'm looking for a less verbose way while still being able to also easily pass any other sort of matching function, like f.e.
f([](int i, int j) { return 3; });
f(std::function<int(int,int)>([](int i, int j) { return 4; }));
Here's a godbolt.
If there's an easy way for C++11 and C++14 this would be great but if there's only one for C++17 and above this would also help a lot.
The issue is std::max not your function.
There is no way you could modify your function to make it accept a set of overloads. A set of overloads is just not something you can pass along. What you can pass along is an object with overloaded operator(). For example
struct foo {
template <typename T> bool operator()(T a,T b){return a+b;}
};
f(foo{}); // OK
std::max however is a function template and you need to instantiate the function before the function can be passed to f. Nothing you can do about that. Though you not necessarily need std::function or static_cast to pick the right overload. As mentioned in a comment you can do
f([](int a, int b) { return std::max(a, b); });
This triggers instantiation of std::max<int> inside the lambda, or if you prefer to select the type inside f you can do similar as in the above example:
f([](auto a, auto b) { return std::max(a,b); });
This lambda expression is similar to the above foo. You have a concrete object and only the operator() is a template which only gets instantiated when called, such that in f you could even do:
template <typename F>
int f(F g)
{
if (some_condition) return g(1,2); // calls std::max<int>
else return g(1.2,1.4); // calls std::max<double>
// (though int is returned anyhow)
}
f([](auto a, auto b) { return std::max(a,b); });
Using template specialization, I've written a series of functions all having the same name and taking the same argument type, but returning data of the type specified by the template parameter:
template<typename T> T f (int x); // Purposefully unimplemented.
template<> inline uint8_t f<uint8_t> (int x) { return f8 [x]; }
template<> inline uint16_t f<uint16_t>(int x) { return f16 [x]; }
template<> inline uint32_t f<uint32_t>(int x) { return f32 [x]; }
template<> inline uint64_t f<uint64_t>(int x) { return f64 [x]; }
Then I can write code like:
uint32_t a = f<uint32_t>(3);
uint64_t b = f<uint64_t>(7);
I've purposefully left the default template unimplemented to produce a linker error if someone tries to use a version of f for anything other than the specialized types for which I've defined it.
I have two questions:
1) Is there some way I can use static_assert() (or whatever) to produce a compile error (instead of a linker error) if someone tries to use the default template that's more friendly than what I get now: undefined reference to `int f(int)'?
2) Is there some way to do this with templates that maintains the same interface to the programmer, but doesn't require template specialization? (I.e., is there some way to avoid a default template altogether?)
namespace fimpl{
template<class T>struct tag_t{};
template<class T>
void fimpl(tag_t<T>, int x)=delete;
}
template<typename T> T f (int x){ using fimpl::fimpl; return fimpl(fimpl::tag_t<T>{}, x); }
now don't specialize; override.
namespace fimpl{ inline uint8_t fimpl(tag_t<uint8_t>, int x) { return f8 [x]; } }
namespace fimpl{ inline uint16_t fimpl(tag_t<uint16_t>, int x) { return f16 [x]; } }
namespace fimpl{ inline uint32_t fimpl(tag_t<uint32_t>, int x) { return f32 [x]; } }
namespace fimpl{ inline uint64_t fimpl(tag_t<uint64_t>, int x) { return f64 [x]; } }
This uses tag dispatching to pick which override instead of using specialization.
If no explicit specialization is found, the =delete template is picked and youmget a compiler error immediately.
Amusingly, if you wanted to extend this with new types, say namespace lib{ struct bigint; } you can put a fimpl(fimpl::tag_t<bigint>, int) overload in namespace lib and it would work. I doubt you'll need that.
You can also do away with f as a template if you are ok with f(tag<uint8_t>, 7) instead of f<uint8_t>(7). Just get rid of fimpl namespace (moving stuff out of it), rename fimpl::fimpl to just f, remove =deleteed template function, add template<class T> constexpr tag_t<T> tag{};. But the syntax is a bit different at point of call.
Is there some way I can use static_assert (or whatever) to produce a compile error (instead of a linker error) if someone tries to use the default template that's more friendly than what I get now: undefined reference to `int f(int)'?
I think the better solution is the one suggested by Passer By in a comment:
template<typename T> T f (int x) = delete;
But if you really want to use a static_assert()... I suppose you can try something as follows
template<typename T>
T f (int x)
{
static_assert( sizeof(T) == std::size_t(-1), "f()!" );
return {};
}
Is there some way to do this with templates that maintains the same interface to the programmer, but doesn't require template specialization? (I.e., is there some way to avoid a default template altogether?)
Isn't clear to me what do exactly want.
You don't want specialization and you want avoid default template?
Supposing that you want only the default template that is available only for a specific set of types, I suppose you can use SFINAE.
To make an example, the following f() is enabled only if T is an integral type.
template<typename T>
typename std::enable_if<std::is_integral<T>{}, T>::type f (int x)
{ return x; }
The following is a full compiling example
#include <iostream>
#include <type_traits>
template<typename T>
typename std::enable_if<std::is_integral<T>{}, T>::type f (int x)
{ return x; }
int main ()
{
auto f16 = f<std::uint16_t>(0);
auto f32 = f<std::uint32_t>(0);
static_assert( std::is_same<decltype(f16), std::uint16_t>{}, "!" );
static_assert( std::is_same<decltype(f32), std::uint32_t>{}, "!" );
// compilation error
// auto fd = f<double>(0);
}
Given a callable object ( a function ) a, and an argument b ( or a series of arguments ), I would like to deduce the type returned from f considering that f is overloaded with multiple signatures.
one of my many attempts is
#include <iostream>
#include <cstdint>
#include <string>
#include <functional>
#include <utility>
#include <typeinfo>
int foo(uint32_t a) { return ((a + 0) * 2); }
bool foo(std::string a) { return (a.empty()); }
/*template <typename A, typename B> auto bar(A a, B b) -> decltype(a(b)) {
return (a(b));
}*/
/*template <typename A, typename B> decltype(std::declval<a(b)>()) bar(A a, B b)
{
return (a(b));
}*/
template <typename A, typename B> void bar(std::function<A(B)> a, B b) {
std::cout << a(b) << "\n";
}
int main() {
// the following 2 lines are trivial and they are working as expected
std::cout << foo(33) << "\n";
std::cout << typeid(decltype(foo(std::string("nothing")))).name() << "\n";
std::cout << bar(foo, 33) << "\n";
//std::cout << bar(foo, std::string("Heinz")) << "\n";
return (0);
}
and 2 templates options are commented out and included in the previous code.
I'm using declval result_of auto decltype without any luck.
How does the overloading resolution process works at compile time ?
If anyone wants to know why I'm trying to get creative with this, is that I'm trying to implement some Currying in C++11 in a workable/neat way.
The problem is that you can't easily create a function object from an overload set: when you state foo or &foo (the function decays into a function pointer in most case, I think) you don't get an object but you get an overload set. You can tell the compiler which overload you want by either calling it or providing its signature. As far as I can tell, you don't want either.
The only approach I'm aware of is to turn your function into an actual function object which makes the problem go away:
struct foo_object
{
template <typename... Args>
auto operator()(Args&&... args) -> decltype(foo(std::forward<Args>(args)...)) {
return foo(std::forward<Args>(args)...);
}
};
With that wrapper which is unfortunately needed for each name, you can trivially deduce the return type, e.g.:
template <typename Func, typename... Args>
auto bar(Func func, Args&&... args) -> decltype(func(std::forward<Args>(args)...)) {
// do something interesting
return func(std::forward<Args>(args)...);
}
int main() {
bar(foo_object(), 17);
bar(foo_object(), "hello");
}
It doesn't quite solve the problem of dealing with overload sets but it gets reasonably close. I experimented with this idea, essentially also for the purpose of currying in the context of an improved system of standard library algorithms and I'm leaning towards the algorithms actually being function objects rather than functions (this is desirable for various other reasons, too; e.g., you don't need to faff about when you want to customize on algorithm with another one).
If foo is overloaded, you need to use the following:
#include <type_traits>
int foo(int);
float foo(float);
int main() {
static_assert(std::is_same<decltype(foo(std::declval<int>())), int>::value, "Nope.");
static_assert(std::is_same<decltype(foo(std::declval<float>())), float>::value, "Nope2.");
}
If it's not, then this will suffice:
#include <type_traits>
bool bar(int);
int main() {
static_assert(std::is_same<std::result_of<decltype(bar)&(int)>::type, bool>::value, "Nope3.");
}
Yes, it is verbose because you're trying to explicitly extract what implicit ad-hoc overloading does for you.
This is actually already implemented for you std::result_of. Here is a possible implementation
template<class>
struct result_of;
// C++11 implementation, does not satisfy C++14 requirements
template<class F, class... ArgTypes>
struct result_of<F(ArgTypes...)>
{
typedef decltype(
std::declval<F>()(std::declval<ArgTypes>()...)
) type;
};
I am trying to build a statically bound delegate class, where the member function is bound at compile time, thereby aiding optimisation.
I have the following code which works exactly how I want it to:
#include <iostream>
namespace thr {
template<typename T, T func>
struct delegate;
template<typename R,
typename C,
typename... A,
R (C::* mem_fun)(A...)>
struct delegate<R(C::*)(A...), mem_fun>
{
delegate(C* obj_)
: _obj(obj_)
{}
R operator()(A... a)
{
return (_obj->*mem_fun)(a...);
}
private:
C* _obj;
};
} // namespace thr
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
typedef thr::delegate<decltype(&foo::bar), &foo::bar> cb;
cb c(&f);
std::cout << c(4, 3);
return 0;
}
However, the usage is not very elegant:
thr::delegate<decltype(&foo::bar), &foo::bar>
I would like to use a function template which deduces the template parameters and returns a delegate instance; something along the lines of (this code does not compile):
template<typename C, typename T, T func>
thr::delegate<T, func> bind(T func, C* obj)
{
return thr::delegate<decltype(func), func>(obj);
}
This would allow for more elegant syntax:
auto cb = bind(&foo::bar, &f);
Is it possible to deduce a non-type parameter in a function template?
Is what I'm trying to achieve even possible?
Would std::function help? http://www2.research.att.com/~bs/C++0xFAQ.html#std-function Your example looks quite close.
I think the compiler supplied STL does pretty horrible things to make it work smoothly. You may want to have a look at as an example before giving up.
Edit: I went out and tried what you try to accomplish. My conclusion is a compile error:
The return type of the bind (delegate) must name the pointer to member because it is your own requirement.
bind should accept the name of the pointer to member to be elegant (i.e. your requirement)
Compiler requires you to not shadow the template parameter with a function parameter or use the name in both parameters and return type.
Therefore one of your requirements must go.
Edit 2: I took the liberty of changing your delegate so bind works as you wish. bind might not be your priority though.
#include <iostream>
namespace thr {
template<typename C,typename R,typename... A>
struct delegate
{
private:
C* _obj;
R(C::*_f)(A...);
public:
delegate(C* obj_,R(C::*f)(A...))
: _obj(obj_),_f(f)
{}
R operator()(A... a)
{
return (_obj->*_f)(a...);
}
};
} // namespace thr
template<class C,typename R,typename... A> thr::delegate<C,R,A...> bind(R(C::*f)(A...),C* obj){
return thr::delegate<C,R,A...>(obj,f);
}
struct foo
{
double bar(int i, int j)
{
return (double)i / (double)j;
}
};
int main()
{
foo f;
auto c = bind(&foo::bar, &f);
std::cout << c(4, 6);
return 0;
}
It is possible to deduce other entities than types in a function signature, but function parameters themselves cannot then be used as template parameters.
Given:
template <size_t I> struct Integral { static size_t const value = I; };
You can have:
template <size_t N>
Integral<N> foo(char const (&)[N]);
But you cannot have:
Integral<N> bar(size_t N);
In the former case, N as the size of the array is part of the type of the argument, in the latter case, N is the argument itself. It can be noticed that in the former case, N appeared in the template parameters list of the type signature.
Therefore, if indeed what you want is possible, the member pointer value would have to appear as part of the template parameter list of the function signature.
There may be a saving grace using constexpr, which can turn a regular value into a constant fit for template parameters:
constexpr size_t fib(size_t N) { return N <= 1 ? 1 : fib(N-1) + fib(N-2); }
Integral<fib(4)> works;
But I am not savvy enough to go down that road...
I do however have a simple question: why do you think this will speed things up ? Compilers are very good at constant propagation and inlining, to the point of being able to inline calls to virtual functions when they can assess the dynamic type of variables at compilation. Are you sure it's worth sweating over this ?