C++: template to check if expression compiles - c++

When writing template specialization with SFINAE you often come to the point where you need to write a whole new specialization because of one small not-existing member or function. I would like to pack this selection into a small statement like orElse<T a,T b>.
small example:
template<typename T> int get(T& v){
return orElse<v.get(),0>();
}
is this possible?

The intent of orElse<v.get(),0>() is clear enough, but if such a thing could exist,
it would have to be be one of:
Invocation Lineup
orElse(v,&V::get,0)
orElse<V,&V::get>(v,0)
orElse<V,&V::get,0>(v)
where v is of type V, and the function template thus instantiated
would be respectively:
Function Template Lineup
template<typename T>
int orElse(T & obj, int(T::pmf*)(), int deflt);
template<typename T, int(T::*)()>
int orElse(T & obj, int deflt);
template<typename T, int(T::*)(), int Default>
int orElse(T & obj);
As you appreciate, no such a thing can exist with the effect that you want.
For any anyone who doesn't get that,
the reason is simply this: None of the function invocations in the Invocation Lineup
will compile if there is no such member as V::get. There's no getting round
that, and the fact that the function invoked might be an instantiation of a
function template in the Function Template Lineup makes no difference whatever.
If V::get does not exist, then any code that mentions it will not compile.
However, you seem to have a practical goal that need not be approached
in just this hopeless way. It looks as if, for a given name foo and an given type R,
you want to be able to write just one function template:
template<typename T, typename ...Args>
R foo(T && obj, Args &&... args);
which will return the value of R(T::foo), called upon obj with arguments args...,
if such a member function exists, and otherwise return some default R.
If that's right, it can be achieved as per the following illustration:
#include <utility>
#include <type_traits>
namespace detail {
template<typename T>
T default_ctor()
{
return T();
}
// SFINAE `R(T::get)` exists
template<typename T, typename R, R(Default)(), typename ...Args>
auto get_or_default(
T && obj,
Args &&... args) ->
std::enable_if_t<
std::is_same<R,decltype(obj.get(std::forward<Args>(args)...))
>::value,R>
{
return obj.get(std::forward<Args>(args)...);
}
// SFINAE `R(T::get)` does not exist
template<typename T, typename R, R(Default)(), typename ...Args>
R get_or_default(...)
{
return Default();
}
} //namespace detail
// This is your universal `int get(T,Args...)`
template<typename T, typename ...Args>
int get(T && obj, Args &&... args)
{
return detail::get_or_default<T&,int,detail::default_ctor>
(obj,std::forward<Args>(args)...);
}
// C++14, trivially adaptable for C++11
which can be tried out with:
#include <iostream>
using namespace std;
struct A
{
A(){};
int get() {
return 1;
}
int get(int i) const {
return i + i;
}
};
struct B
{
double get() {
return 2.2;
}
double get(double d) {
return d * d;
}
};
struct C{};
int main()
{
A const aconst;
A a;
B b;
C c;
cout << get(aconst) << endl; // expect 0
cout << get(a) << endl; // expect 1
cout << get(b) << endl; // expect 0
cout << get(c) << endl; // expect 0
cout << get(a,1) << endl; // expect 2
cout << get(b,2,2) << endl; // expect 0
cout << get(c,3) << endl; // expect 0
cout << get(A(),2) << endl; // expect 4
cout << get(B(),2,2) << endl; // expect 0
cout << get(C(),3) << endl; // expect 0
return 0;
}
There is "compound SFINAE" in play in the complicated return type:
std::enable_if_t<
std::is_same<R,decltype(obj.get(std::forward<Args>(args)...))
>::value,R>
If T::get does not exist then decltype(obj.get(std::forward<Args>(args)...)
does not compile. But if it does compile, and the return-type of T::get is
something other than R, then the std::enable_if_t type specifier does not
compile. Only if the member function exists and has the desired return type R
can the R(T::get) exists case be instantiated. Otherwise the
catch-all R(T::get) does not exist case is chosen.
Notice that get(aconst) returns 0 and not 1. That's as it should be,
because the non-const overload A::get() cannot be called on a const A.
You can use the same pattern for any other R foo(V & v,Args...) and
existent or non-existent R(V::foo)(Args...).
If R is not default-constructible, or if you want the default R that
is returned when R(V::foo) does not exist to be something different from
R(), then define a function detail::fallback (or whatever) that returns the
desired default R and specify it instead of detail::default_ctor
How nice it would be it you could further template-paramaterize the pattern
to accomodate any possible member function of T with any possible return
type R. But the additional template parameter you would need for that would
be R(T::*)(typename...),and its instantiating value would have to be
&V::get (or whatever), and then the pattern would
force you into the fatal snare of mentioning the thing whose existence is in doubt.

Yes, this is more or less possible. It is known as a "member detector". See this wikibooks link for how to accomplish this with macros. The actual implementation will depend on whether you are using pre- or post-C++11 and which compiler you are using.

Related

C++ template class error: function returning a function

I want to make a simple logger which automatically runs a function and returns its value.
The class is defined as:
template <typename R, typename... Args>
class Logger3
{
Logger3(function<R(Args...)> func,
const string& name):
func{func},
name{name}
{}
R operator() (Args ...args)
{
cout << "Entering " << name << endl;
R result = func(args...);
cout << "Exiting " << name << endl;
return result;
}
function<R(Args...)> func;
string name;
};
I want to pass the following simple add function to the logger:
int add(int a, int b)
{
cout<<"Add two value"<<endl;
return a+b;
}
By calling it this way:
auto caller = Logger3<int(int,int)>(add,"test");
However, it generates the following errors:
error: function returning a function
133 | Logger3(function<R(Args...)> func,
| ^~~~~~~
decorator.h:138:7: error: function returning a function
138 | R operator() (Args ...args)
| ^~~~~~~~
decorator.h:145:26: error: function returning a function
145 | function<R(Args...)> func;
There are 3 issues in your code:
The Logger3 class template requires R to be the return value of the function (and Args it's arguments).
(R is not a function type as implied by your attempt to instantiate Logger3).
Therefore instantiating the Logger3 in your case of a function that gets 2 ints and returns an int should be:
auto caller = Logger3<int, int, int>(add, "test");
Your Logger3 constructor should be public in order to invoke it from outside the class.
For efficiency reasons, you should use std::forward to forward the arguments from operator() to your function. This will avoid copy of the arguments (more significant in cases where their types are more complex than ints).
Note that in order for std::forward to work as expected, operator() has to be itself a variadic template using forwarding references (see below).
Complete fixed version:
#include <string> // std::string
#include <functional> // std::function
#include <utility> // std::forward, std::declval
#include <iostream> // std::cout
template <typename R, typename... Args>
class Logger3
{
public:
Logger3(std::function<R(Args...)> func,
const std::string& name) :
func{ func },
name{ name }
{}
// Template with forwarding references to avoid copies
// 'typename' arg is for SFINAE, and only enables if a
// function accepting 'Args...' can evaluate with 'UArgs...'
template <typename...UArgs,
typename = decltype(std::declval<R(*)(Args...)>()(std::declval<UArgs>()...))>
R operator() (UArgs&&...args)
{
std::cout << "Entering " << name << std::endl;
R result = func(std::forward<UArgs>(args)...);
std::cout << "Exiting " << name << std::endl;
return result;
}
private:
std::function<R(Args...)> func;
std::string name;
};
int add(int a, int b)
{
std::cout << "Add two value" << std::endl;
return a + b;
}
int main()
{
auto caller = Logger3<int, int, int>(add, "test");
auto res = caller(3, 4);
std::cout << "result: " << res << std::endl;
return 0;
}
Output:
Entering test
Add two value
Exiting test
result: 7
Demo: Godbolt.
A side note: better to avoid using namespace std - see here: Why is "using namespace std;" considered bad practice?.
You need to use template class partial specialization to get the type of R.
template <typename F>
class Logger3;
template <typename R, typename... Args>
class Logger3<R(Args...)>
{
// implementation details
};
which makes int match the template parameter R of the partial specialization when you explicitly specify Logger3<int(int,int)>.

Is this considered valid c++11 or c++14? Or is gcc/clang getting it wrong?

While trying to solve Is it possible to tell if a class has hidden a base function in C++?, I generated this:
#include <type_traits>
#include <iostream>
#define ENABLE_IF(...) std::enable_if_t<(__VA_ARGS__), int> = 0
template<class T, class B, ENABLE_IF(std::is_same<void(T::*)(), decltype(&T::x)>::value)>
auto has_x_f(T*) -> std::true_type;
template<class T, class B>
auto has_x_f(B*) -> std::false_type;
template<class T, class B>
using has_x = decltype(has_x_f<T, B>((T*)nullptr));
template<typename T>
struct A
{
void x() {}
static const bool x_hidden;
template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}
template <typename R, ENABLE_IF(std::is_same<T, R>::value && !x_hidden)>
void y(R value)
{
std::cout << "x() is not hidden" << std::endl;
}
//using t = std::integral_constant<bool, x_hidden>;
};
struct B : A<B>
{
void x() {}
};
struct C : A<C>
{
};
template<typename T>
const bool A<T>::x_hidden = has_x<T, A<T>>::value;
int main()
{
B b;
C c;
std::cout << "B: ";
std::cout << b.x_hidden << std::endl;
std::cout << "C: ";
std::cout << c.x_hidden << std::endl;
std::cout << "B: ";
b.y(b);
std::cout << "C: ";
c.y(c);
return 0;
}
Which outputs what I want:
B: 1
C: 0
B: x() is hidden
C: x() is not hidden
clang and gcc both compile and execute this "correctly", but vc++ doesn't (though I am aware that there are problems with it working properly with expressions similar to template <typename T> ... decltype(fn(std::declval<T>().mfn()))).
So my question is, is this considered valid or will it break later on? I'm also curious about the x_hidden being able to be used as a template parameter in the functions but not being able to use it in using t = std::integral_constant<bool, x_hidden>. Is that just because the template's type isn't fully declared at this point? If so, why did using it work for the function declarations?
If x_hidden is false, there is no template arguements for which this template function
template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value) {
std::cout << "x() is hidden" << std::endl;
}
can be instantiated, so your program is ill formed no diagnostic required. This is a common hack, its illegality may be made clear or even legal at some point.
There may be a reason for using has_x_f instead of just directly initializing is_hidden with the is_same clause, but it isn't demonstrated in your code.
For any template specialization, there must be arguments which would make the instantiation valid. If there are not, the program is ill-formed no diagnostic required.
I believe this clause is in the standard to permit compilers to do more advanced checks on templates, but not require them.
template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}
the compiler is free to notice x_hidden is false, and say "it doesn't matter what is_same<T,R> is", and deduce that no template arguments could make this specialization valid. Then generate an error.
An easy hack is
template <class T2=T, class R,
ENABLE_IF(std::is_same<T2, R>::value && has_x<T2, A<T2>>::value)
>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}
where we sneak another template argument in that equals T usually. Now, the compiler has to admit the possibility that T2 passes the has_x test, and that the passed argument is R. Users can bypass this by manually passing the "wrong" T2.
This may not solve everything. The standard is a bit tricky to read here, but one reading states that if within the body of y() we go and assume that our T itself has x(), we still violate the rule of the possibility of a valid template instantiation.
[temp.res] 14.6/8 (root and 1)
Knowing which names are type names allows the syntax of every template to be checked. The program is ill-formed, no diagnostic required, if:
no valid specialization can be generated for a template [...] and the template is not instantiated, or
No valid specialization for
template <typename R, ENABLE_IF(std::is_same<T, R>::value && x_hidden)>
void y(R value)
{
std::cout << "x() is hidden" << std::endl;
}
can be generated if x_hidden is false. The exitence of another overload is immaterial.
If you fix it using the T2 trick, the same rule holds if the body assumes T=T2.
Three are words in the standard that attempt to not cause the template to be instantiated in certain contexts, but I am unsure if that makes the above code well formed or not.
I tried compiling your code with the Intel C++ compiler(icpc (ICC) 17.0.2 20170213), and it would not compile with the following message:
main.cpp(30): error: expression must have a constant value
template <typename R, ENABLE_IF(std::is_same<T, R>::value && !x_hidden)>
^
/home/com/gcc/6.2.0/bin/../include/c++/6.2.0/type_traits(2512): error: class "std::enable_if<<error-constant>, int>" has no member "type"
using enable_if_t = typename enable_if<_Cond, _Tp>::type;
^
detected during instantiation of type "std::enable_if_t<<error-constant>, int>" at line 30 of "main.cpp"
main.cpp(62): error: more than one instance of overloaded function "B::y" matches the argument list:
function template "void A<T>::y(R) [with T=B]"
function template "void A<T>::y(R) [with T=B]"
argument types are: (B)
object type is: B
b.y(b);
I was however able to compile the following with both the Intel compiler and GCC.
#include <iostream>
#define ENABLE_IF(...) std::enable_if_t<(__VA_ARGS__), int> = 0
template<class T, class B, ENABLE_IF(std::is_same<void(T::*)(), decltype(&T::x)>::value)>
auto has_x_f(T*) -> std::true_type;
template<class T, class B>
auto has_x_f(B*) -> std::false_type;
template<class T, class B>
using has_x = decltype(has_x_f<T, B>((T*)nullptr));
template<class T>
class A
{
public:
T& self() { return static_cast<T&>(*this); }
void x() { }
template
< class TT = T
, typename std::enable_if<has_x<TT, A<TT> >::value, int>::type = 0
>
void y()
{
std::cout << " have x hidden " << std::endl;
// if you are so inclined, you can call x() in a "safe" way
this->self().x(); // Calls x() from class "Derived" (Here class B)
}
template
< class TT = T
, typename std::enable_if<!has_x<TT, A<TT> >::value, int>::type = 0
>
void y()
{
std::cout << " does not have x hidden " << std::endl;
// if you are so inclined, you can call x() in a "safe" way
this->self().x(); // Calls x() from class "Base" (Here class A)
}
};
class B : public A<B>
{
public:
void x() { }
};
class C : public A<C>
{
};
int main()
{
B b;
C c;
b.y();
c.y();
return 0;
}
I am not aware whether or not this is incorrect according to the standard however, but as I see it you do not run into the problem mentioned in one of the other answers, that you have a template that cannot be instantiated.
EDIT: I was able to get to compile on MSVC 2017 by some "old-times" template metaprogramming tricks, and using classes instead of functions.
If I use this implementation of has_x instead it compiles:
template<class T, bool>
struct has_x_impl;
template<class T>
struct has_x_impl<T, true>: std::true_type
{
};
template<class T>
struct has_x_impl<T, false>: std::false_type
{
};
template<class T>
using has_x = has_x_impl<T, std::is_same<void(T::*)(), decltype(&T::x)>::value>;
Full code on Wandbox here.
I had a bit of a code clean-up (got rid of the out-of-line x_hidden declaration) and ended up with the following. I also fixed it slightly based on #Yakk's answer above, to avoid [temp.res]/8 invalidating it.
#include <type_traits>
#include <iostream>
#include <cassert>
#define ENABLE_IF(...) std::enable_if_t<(__VA_ARGS__), int> = 0
template<class T, class Base, ENABLE_IF(std::is_same<void(T::*)(), decltype(&T::x)>::value)>
auto has_x_f() -> std::true_type;
template<class T, class Base, ENABLE_IF(std::is_same<void(Base::*)(), decltype(&T::x)>::value)>
auto has_x_f() -> std::false_type;
template<class T, class Base>
using has_x = decltype(has_x_f<T, Base>());
template<typename T>
struct A
{
void x() {}
static bool constexpr x_hidden() {
return has_x<T, A<T>>::value;
}
void y()
{
assert(x_hidden() == y_<T>(nullptr) );
}
void y2()
{
if constexpr(x_hidden()) {
typename T::BType i = 1;
(void)i;
} else {
typename T::CType i = 1;
(void)i;
}
}
private:
template <typename R, typename T2=T, ENABLE_IF(A<T2>::x_hidden())>
static bool y_(R*)
{
std::cout << "x() is hidden" << std::endl;
return true;
}
template <typename R, typename T2=T, ENABLE_IF(!A<R>::x_hidden())>
static bool y_(T*)
{
std::cout << "x() is not hidden" << std::endl;
return false;
}
};
struct B : A<B>
{
void x() {}
using BType = int;
};
static_assert(std::is_same<decltype(&B::x), void(B::*)()>::value, "B::x is a member of B");
struct C : A<C>
{
using CType = int;
};
static_assert(std::is_same<decltype(&C::x), void(A<C>::*)()>::value, "C::x is a member of A<C>");
int main()
{
B b;
C c;
std::cout << "B: ";
std::cout << B::x_hidden() << std::endl;
std::cout << "C: ";
std::cout << C::x_hidden() << std::endl;
std::cout << "B: ";
b.y();
b.y2();
std::cout << "C: ";
c.y();
c.y2();
return 0;
}
Live demo on wandbox -- gcc and clang are both happy with it.
MSVC 2017 complained
error C2064: term does not evaluate to a function taking 0 arguments
for both uses of A<T2>::x_hidden(), when instantiating A<B> for B to inherit from.
MSVC 2015 gave the same complaint, and then suffered an Internal Compiler Error. ^_^
So I think this is valid, but exercises MSVC's constexpr or template instantiation machinery in unpleasant ways.
Per the example in [expr.unary.op]/3, the type of &B::x is void (B::*)(), and the type of &C::x is void (A<C>::*)(). So the first has_x_f() will be present when T is B, and the second has_x_f() will be present when T is C and Base is A<C>.
Per [temp.inst]/2, instantiating the class instantiates declarations but not definitions of the members. Per [temp.inst]/3 and 4, member function definitions (including template functions) are not instantiated until required.
Our declarations here are currently different, as the use of R and T2 mean the compiler cannot determine the truth or falsehood of either size of the &&.
The use of the different parameter types helps MSVC, which would otherwise see them as redefinitions of the same template member template function. My reading of [temp.inst]/2 says this is not needed, as they're only redefintions when we instantiate them, and they cannot be instantiated at the same time. Because we use A<T2>::x_hidden() and !A<R>::x_hidden(), the compiler cannot know that they are mutually exclusive at this time. I don't think it's necessary to do that to avoid [temp.res]/8, simply using A<R>::x_hidden() seems safe-enough to me. This was also to ensure that in the two templates, R as actually used.
From there on, it's pretty easy. y() shows we have the right values coming from both paths.
Depend on your use-case, you could use if constexpr with x_hidden() to avoid all the template magic in y_(), per y2() above.
This avoids the issue with [temp.res]/8 described in #Yakk's answer, as the problematic clause [temp.res]/8.1 is that the template is ill-formed if
no valid specialization can be generated for a template or a substatement of a constexpr if statement within a template and the template is not instantiated, [...]
So as long as you instantiate A<T>::y2() for some T, then you're not subject to this clause.
The y2() approach has the advantage of working with MSVC2017, as long as you pass in the "/std:c++latest" compiler flag.

Get type of function first parameter for template function return type

I have the following template function:
template<class T, class F> T function(F& f) {
...
T t;
f(t);
return t;
}
It's expected to be used with F with the form
void some_function(SomeType& s);
in this way
function<SomeType>(some_function);
The first template argument seems redundant because can be deduced from the parameters of the parameter function.
The question is
Exists a way to get rid of the first template parameter?
Something like
template<class F> first_param_type<F> function(F& f) {
...
first_param_type<F> t;
f(t);
return t;
}
So that I can use it as
function(some_function);
template<class T>
T function( void(*f)(T&) ) {
...
T t;
f(t);
return t;
}
solves the problem as stated. The general problem cannot be solved (where F is an arbitrary callable), as callables in C++ can accept more than one type, and deducing what types are acceptable cannot be solved in the general case.
If you had a list of types you support, it an be solved in general.
The basic problem in C++14 is function([](auto&x){ std::cout << x << '\n'; }). The same problem exists in C++11 with function objects with a template operator(). The fact that auto-lambdas are supported in C++14 means that such objects are going to become more and more common in the future.
Consider changing your design so that the signature of your F is T() rather than void(T&). Then we get:
template<class F>
std::result_of_t<F()>
function( F&& f ) {
...
return std::forward<F>(f)();
}
or typename std::result_of<F()>::type in C++11.
I hope I understood your question, maybe I am wrong...
First of all I expect your template function must be called and for the call it needs additional parameters which I could not found in your example code.
But ok, what I expect what you can do:
#include <iostream>
using namespace std;
template <typename RetType, typename ... Parms>
auto TemplateFunction ( RetType(*ptr)(Parms ...), Parms ... parms ) -> RetType
{
RetType ret;
ret = (*ptr)( parms...);
cout << "Value ret in Wrapper is:" << ret << endl;
return ret;
}
double AnyFunc(int a, int b) { return 3.14 * a + b; }
std::string OtherFunc( ) { return "Hallo"; }
int main()
{
double result = TemplateFunction(&AnyFunc, 1,3);
cout << "Result is " << result << endl;
cout << TemplateFunction(&OtherFunc) << endl;
}
As you already mentioned, there is no need to give the return type as additional parameter, because it can be found in the given as type in the presented function pointer to the template.
The wrapper template will work for all return types but not for void!
UPDATE
I absolutely agree with Yakk's answer I just wanted to mention an other but very similar way:
#include <functional>
template < class Type >
Type myFunction( const std::function< void( Type& ) >& aFunction )
{
Type instance;
aFunction( instance );
return instance;
}

Deducing type for overloaded functions - currying

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;
};

Haskell-like `const` in C++

So in the past few weeks, I've been experimenting with functional-programming type solutions to problems in C++11, and from time to time, I've been in a situation where I need a function that returns a constant value.
In Haskell, there is a function
const :: a -> b -> a
const x = \_ -> x
that returns a function that evaluates to const's original argument, no matter what argument is supplied to it. I would like to create something similar in C++11. Such constructions are useful for signifying special behavior in functions (a constant function of true sent to a filter would leave the data intact). Here's my first attempt:
template<class T>
std::function<T(...)> constF(T x) {
return ([x](...) { return x; });
}
This compiles on its own, but any attempt to use it results in incomplete-type errors. My second attempt was this:
template<class T, class... Args>
std::function<T(Args...)> constF(T x) {
return ([x](Args...) { return x; });
}
This comes closer, but doesn't allow me to supply any arguments, unless I explicitly state them.
auto trueFunc1 = constF(true);
auto trueFunc2 = constF<bool, int>(true);
cout << trueFunc1() << endl; //works
cout << trueFunc1(12) << endl; //doesn't compile
cout << trueFunc2(12) << endl; //works
Ideally, a correct construction would produce no difference between trueFunc1 and trueFunc2.
Is this even possible in C++?
Since C++11 doesn't have generic or variadic lambdas, I'd write a functor template class:
template <typename T>
// requires CopyConstructible<T>
class const_function {
T value;
public:
template <typename U, typename = typename std::enable_if<std::is_convertible<U,T>::value>::type>
const_function(U&& val) :
value(std::forward<U>(val)) {}
template <typename... Args>
T operator () (Args&&...) const {
return value;
}
};
and a nice type-deducing wrapper to make them:
template <typename T>
const_function<typename std::remove_reference<T>::type>
constF(T&& t) {
return {std::forward<T>(t)};
}
In C++1y, I think the simple equivalent is:
template <typename T>
auto constF(T&& t) {
return [t{std::forward<T>(t)}](auto&&...){return t;};
}