Call less constrained functionally equivalent function - c++

Consider the following code:
#include <iostream>
#include <type_traits>
struct A;
template<class T>
concept HasParent = std::is_convertible_v<typename T::parent*, A*>;
struct A{};
struct B : A { using parent = A; };
template<class T> int foo(T*) { return 1; }
template<HasParent T> int foo(T*)
{
// call the other one?
return 2;
}
int main()
{
B b;
std::cout << foo(&b) << std::endl; // displays 2
return 0;
}
Is it possible to call the general foo<T>(T*) function from foo<HasParent T>(T*)?
(this is a (functional) example, but I can link the complete code on github)

Is it possible to call the general foo<T>(T*) function from foo<HasParent T>(T*)?
You need some way to differentiate between the two functions in order to do this.
For example:
template <typename T> void foo(T);
template <typename T> requires true auto foo(T) -> int;
The second one is obviously more constrained than the first, for all T, so foo(42) calls the second. But, you can differentiate between the two:
auto unconstrained = static_cast<void(*)(int)>(foo);
Here, the constrained function template returns int so it's not a viable candidate and we get the unconstrained one instead.
In your example, both return int, so this particular trick doesn't work. But the key is that you need some way to differentiate the two templates.
A better way is probably:
template <typename T, std::monostate M = {}>
void foo(T);
template <typename T> requires true
void foo(T arg) {
foo<T, std::monostate{}>(arg); // calls the unconstrained one
}
Using monostate here is kinda cute since it doesn't actually change the number of template instantiations (there's only one monostate... ). foo(42) calls the second, which calls the first. Demo.
But it might be better to just add a new function and have both the unconstrained and constrained version of the function template invoke that one (in the sense that it's arguably less cryptic than the monostate approach).

Related

Match template unconditionally

I would like to call a template function even if std::enable_if_t doesn't resolve to true. It would allow me to reuse one of my existent templates in other context.
Minimal example:
#include <iostream>
#include <type_traits>
template<typename T,
typename = typename std::enable_if<std::is_same<T, int>::value>::type>
auto foo(T t) {
std::cout << t << std::endl;
return t;
}
template<typename T>
auto bar(T t) {
foo(t);
}
int main() {
int i = 42;
foo(i); // ok already
// foo("42"); // shouldn't
bar("42"); // should
}
I tried to solve it bydeclaring a bool in template argument list of foo and specify it when calling foo in bar, but I didn't quite manage to compile it without changing how foo is getting called in already existent code.
Is there any way to accomplish this? Maybe std::disjunction?
What you want doesn't make sense. Either a call to foo is valid or it isn't. It shouldn't matter who does it. enable_if is used to ward templates from cases where a particular parameter cannot work (or you have an alternate definition where it can). For example, if the definition is going to use a copy constructor, but the type doesn't have one. What you're using it for here doesn't fit that use case.
You can pull out the logic of foo into a separate function that both foo and bar call, if you really need to do something like this.
Using this SFINAE technique, you can call foo for “forbidden” types by not using the default template argument (and therefore not using deduction):
template<typename T>
auto bar(T t) {
return foo<T,void>(t);
}
This is of course sometimes cited as a weakness of default-type-template-argument SFINAE, along with its inability to constrain multiple, otherwise-equivalent overloads.

Calling a member function if it exists, falling back to a free function and vice-versa

Can I write a template function taking an argument T that calls a member function foo if it exists on T, and if it doesn't calls a free function foo(T) instead (and fails to compile if neither exists)?
Something like:
template<typename T>
int call_foo(T t) {
// if T::foo() exists
return t.foo();
// else return foo(t);
}
How about the reverse case: preferring a free function foo before the member function? I cannot use any features introduced after C++11.
This isn't too hard. There are many methods of checking whether an arbitrary expression is valid. You can combine this with if constexpr in C++17 or tag dispatch earlier to get the behaviour you desire.
This uses C++17, but everything can be done in prior versions:
#include <type_traits>
#include <utility>
// This is just one way to write a type trait, it's not necessarily
// the best way. You could use the Detection Idiom, for example
// (http://en.cppreference.com/w/cpp/experimental/is_detected).
template <typename T, typename = void>
struct has_member_fn
: std::false_type
{};
// std::void_t is a C++17 library feature. It can be replaced
// with your own implementation of void_t, or often by making the
// decltype expression void, whether by casting or by comma operator
// (`decltype(expr, void())`)
template <typename T>
struct has_member_fn<T,
std::void_t<decltype(std::declval<T>().foo())>>
: std::true_type
{};
template <typename T, typename = void>
struct has_free_fn
: std::false_type
{};
template <typename T>
struct has_free_fn<T,
// Be wary of ADL. You're basically asking the compiler,
// "What's the result of foo(T{}) if I were to call that
// here?" That syntax can call functions via ADL
std::void_t<decltype(foo(std::declval<T>()))>>
: std::true_type
{};
template <typename T>
int call_foo(T t) {
// if constexpr is C++17, but you can use tag dispatch to
// do the same in prior versions
if constexpr (has_member_fn<T>::value) {
return t.foo();
} else {
// you could make this an `else if constexpr (has_free_fn<T>::value)`
// and provide a better case for if neither exists
return foo(t);
}
}
Live on Godbolt
Pre C++17 you can's compile/not compile different parts of the same function with if constexpr.
So, pre C++17, you have to do, somewhere, two different functions.
An example: if you prepare a couple of helper functions
template <typename T>
auto call_foo_h (T t, int) -> decltype( t.foo() )
{ return t.foo(); }
template <typename T>
auto call_foo_h (T t, long) -> decltype( foo(t) )
{ return foo(t); }
that are SFINAE enabled only if T::foo() exist (the first one) or if a free foo() exist (the second one), you can write call_foo() as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0); }
//......................^ a int value
Observe the second (unused) parameter in call_foo_h(); an int in the T::foo() version, a long in the free version.
Here is the trick: calling call_foo_h with an int (0) you call preferably the int version (the T::foo()), when available, and the long version otherwise.
How about the reverse case: preferring a free function foo before the member function?
In this case write call_foo() as follows
template <typename T>
int call_foo (T const & t)
{ return call_foo_h(t, 0L); }
//......................^^ a long value
That is: call call_foo_h with a long value, giving the precedence to the free foo() version.

Recursive variadic function template

I want to write a class method that takes a template parameter pack, but zero arguments, and "iterate" over the types:
struct Bar {
template <typename T, typename... Ts>
void foo() {
// something with T that involves Bar's members
foo<Ts...>();
}
};
What is the preferred way to implement this?
You may use the following:
struct Bar {
template <typename... Ts>
void foo() {
int dummy[] = {0 /*Manage case where Ts is empty*/,
(bar<Ts>(), void() /* To avoid overload `operator,` */, 0)...};
(void) dummy; // suppress warning for unused variable.
}
template <typename T>
void bar()
{
// something with T that involves Bar's members
}
};
In C++17, it can be simplified with Folding expression:
struct Bar {
template <typename... Ts>
void foo() {
(static_cast<void>(bar<Ts>()), ...);
}
template <typename T>
void bar()
{
// something with T that involves Bar's members
}
};
template<class...Fs>
void do_in_order(Fs&&...fs) {
int _[]={0, ( std::forward<Fs>(fs)(), void(), 0 )...};
(void)_;
}
hides the syntax required to execute a pack of function objects in left to right order.
Then:
struct Bar {
template <class... Ts>
void foo() {
do_in_order([&]{
using T = Ts;
// code
}...);
}
};
and in a conforming compiler, we will run the // code with T being each type from left to right.
Note that some compilers claiming to be C++11 compilers may fail to compile the above.
The advantage of this technique is that it hides the nasty "expand and evaluate templates" code within a function with a clear name. You write do_in_order once, and it usually suffices for almost every use of that array-expansion trick.
There are a two important reasons to use this kind of esoteric syntax instead of the "more simple" recursive solutions.
First, it makes things easier for the optimizer. Optimizers sometimes give up after a pile of recursive calls.
Second, the sum of the lengths names of the function signatures for the traditional recursive functions grow at O(n^2). If you use helper types, the total length of the names is also O(n^2). Unless you are careful, this can cause compile time, link time, and binary size bloat.
In C++1z there are plans for some "fold" syntax that may make the esoteric parts of the above less esoteric.
I like overloaded functions and using a typelist:
#include <iostream>
#include <typeinfo>
template <typename ...Ts> struct typelist { };
void foo_impl(typelist<> )
{
// we are finished
}
template <typename T, typename ...Ts>
void foo_impl(typelist<T, Ts...> )
{
std::cout << typeid(T).name() << ", ";
foo_impl(typelist<Ts...>{});
}
template <typename ...Ts>
void foo()
{
std::cout << "called with <";
foo_impl(typelist<Ts...>{});
std::cout << ">" << std::endl;
}
int main()
{
foo<int, char, float>();
}

Function template specialization with overloads with different number of parameters

Consider the following (invalid) code sample:
// a: base template for function with only one parameter
template<typename T>
void f(T t) { }
// b: base tempalte for function with two parameters
template<typename T1, typename T2>
void f(T1 t1, T2 t2) { }
// c: specialization of a for T = int
template<>
void f<int>(int i) { }
// d: specialization for b with T1 = int - INVALID
template<typename T2>
void f<int, T2>(int i, T2 t2) { }
int main() {
f(true); // should call a
f(true, false); // should call b
f(1); // should call c
f(1, false); // should call d
}
I've read this walk-through on why, in general, partial function template specializations won't work, and I think I understand the basic reasoning: there are cases where function template specializations and overloading would make certain calls ambiguous (there are good examples in the article).
However, is there a reason why this specific example wouldn't work, other than "the standard says it shouldn't"? Does anything change if I can guarantee (e.g. with a static_assert) that the base template is never instantiated? Is there any other way to achieve the same effect?
What I actually want to achieve is to create an extendable factory method
template<typename T>
T create();
which also has a few overloads taking input parameters, e.g.
template<typename T, typename TIn>
T create(TIn in);
template<typename T, typename TIn1, typename TIn2>
T create(TIn1 in1, TIn2 in2);
In order to ensure that all necessary factory methods are present, I use static_assert in the function base templates, so that a compiler error is generated if the create method is called with template arguments for which no specialization has been provided.
I want these to be function templates rather than class templates because there will be quite a lot of them, and they will all use input from the same struct hierarchy, so instantiating 10 factories instead of one comes with some overhead that I'd like to avoid (not considering the fact that the code gets much easier to understand this way, if I can just get it to work...).
Is there a way to get around the problem outlined in the first half of this post, in order to achieve what I've tried to get at with the second half?
In response to iavr:
I could do this with plain overloading, which would (given the templates above) give something like
template<typename TIn2>
A create(bool, TIn2);
template<typename TIn2>
A create(int, TIn2);
if I need two different partial specializations with T = A, TIn1 specified and TIn2 still unspecified. This is a problem, since I have some cases (which are really text-book cases for meta-programming and templates) where I know that, for example, one of the arguments will be a std::string, and the other will be of some type that has a property fields and a property grids, which are of types std::vector<field> and std::vector<grid> respectively. I don't know all the types that will ever be supplied as the second argument - I know for sure that there will be more of them than the ones I currently have implemented - but the implementation of the method will be exactly the same.
While writing up this update, I think I've figured out a way to redesign the implementations so that there is no need for the partial specialization - basically, I do the following to cover the case outlined above:
template<>
A create<A, std::vector<field>, std::vector<grid>>(std::vector<field> fs, std::vector<grid> gs);
and then I have to change the calling signature slightly, but that's OK.
I share your concerns that maybe in this particular case there would be no problem having function template partial specializations, but then again, that's the way it is, so what would be your problem using plain overloading?
// a: base template for function with only one parameter
template<typename T>
void f(T t) { }
// b: base template for function with two parameters
template<typename T1, typename T2>
void f(T1 t1, T2 t2) { }
// c: specialization of a for T = int
void f(int i) { }
// d: specialization for b with T1 = int
template<typename T2>
void f(int i, T2 t2) { }
This also takes less typing and I get this is why you don't want to use function objects (which would have partial specialization).
Here is a simple workaround using a class template specialization:
template <typename, typename...>
struct Creator;
template <typename T, typename TIn>
struct Creator<T, TIn>
{
T call(TIn in)
{
// ...
}
};
template<typename T, typename TIn1, typename TIn2>
struct Creator<T, TIn1, TIn2>
{
T call(TIn1 in1, TIn2 in2)
{
// ...
}
};
template <typename R, typename... Arguments>
R Create(Arguments&&... arguments)
{
return Creator<R, Arguments...>::call(std::forward<Arguments>(arguments)...);
}
If you don't want overloading, and want to be able to specialize from a separate file, then I think you should base it on the solution on the link from your question. It involves making a static method on a class that you specialize. From my reading of the question, you're only interested in specializing on the T, not on the number of arguments, which you intend to forward. In C++11, you can do the following:
#include <iostream>
#include <utility>
using namespace std;
template<typename T>
struct factory_impl;
// Left unspecified for now (which causes compliation failure if
// not later specialized
template<typename T, typename... Args>
T create(Args&&... args)
{
return factory_impl<T>::create(std::forward<Args>(args)...);
}
// Note, this can be specified in a header in another translation
// unit. The only requirement is that the specialization
// be defined prior to calling create with the correct value
// of T
template<>
struct factory_impl<int>
{
// int can be constructed with 0 arguments or 1 argument
static int create(int src = 0)
{
return src;
}
};
int main(int argc, char** argv)
{
int i = create<int>();
int j = create<int>(5);
// double d = create<double>(); // Fails to compile
std::cout << i << " " << j << std::endl;
return 0;
}
Live example http://ideone.com/7a3uRZ
Edit: In response to your question, you could also make create a member function of a class, and pass along some of that data with the call or take action before or after
struct MyFactory
{
template<typename T, typename... Args>
T create(Args&&... args)
{
T ret = factory_impl<T>::create(data, std::forward<Args>(args)...);
// do something with ret
return ret;
}
Foo data; // Example
};

How to call a templated function if it exists, and something else otherwise?

I want to do something like
template <typename T>
void foo(const T& t) {
IF bar(t) would compile
bar(t);
ELSE
baz(t);
}
I thought that something using enable_if would do the job here, splitting up foo into two pieces, but I can't seem to work out the details. What's the simplest way of achieving this?
There are two lookups that are done for the name bar. One is the unqualified lookup at the definition context of foo. The other is argument dependent lookup at each instantiation context (but the result of the lookup at each instantiation context is not allowed to change behavior between two different instantiation contexts).
To get the desired behavior, you could go and define a fallback function in a fallback namespace that returns some unique type
namespace fallback {
// sizeof > 1
struct flag { char c[2]; };
flag bar(...);
}
The bar function will be called if nothing else matches because the ellipsis has worst conversion cost. Now, include that candidates into your function by a using directive of fallback, so that fallback::bar is included as candidate into the call to bar.
Now, to see whether a call to bar resolves to your function, you will call it, and check whether the return type is flag. The return type of an otherwise chosen function could be void, so you have to do some comma operator tricks to get around that.
namespace fallback {
int operator,(flag, flag);
// map everything else to void
template<typename T>
void operator,(flag, T const&);
// sizeof 1
char operator,(int, flag);
}
If our function was selected then the comma operator invocation will return a reference to int. If not or if the selected function returned void, then the invocation returns void in turn. Then the next invocation with flag as second argument will return a type that has sizeof 1 if our fallback was selected, and a sizeof greater 1 (the built-in comma operator will be used because void is in the mix) if something else was selected.
We compare the sizeof and delegate to a struct.
template<bool>
struct foo_impl;
/* bar available */
template<>
struct foo_impl<true> {
template<typename T>
static void foo(T const &t) {
bar(t);
}
};
/* bar not available */
template<>
struct foo_impl<false> {
template<typename T>
static void foo(T const&) {
std::cout << "not available, calling baz...";
}
};
template <typename T>
void foo(const T& t) {
using namespace fallback;
foo_impl<sizeof (fallback::flag(), bar(t), fallback::flag()) != 1>
::foo(t);
}
This solution is ambiguous if the existing function has an ellipsis too. But that seems to be rather unlikely. Test using the fallback:
struct C { };
int main() {
// => "not available, calling baz..."
foo(C());
}
And if a candidate is found using argument dependent lookup
struct C { };
void bar(C) {
std::cout << "called!";
}
int main() {
// => "called!"
foo(C());
}
To test unqualified lookup at definition context, let's define the following function above foo_impl and foo (put the foo_impl template above foo, so they have both the same definition context)
void bar(double d) {
std::cout << "bar(double) called!";
}
// ... foo template ...
int main() {
// => "bar(double) called!"
foo(12);
}
litb has given you a very good answer. However, I wonder whether, given more context, we couldn't come up with something that's less generic, but also less, um, elaborate?
For example, what types can be T? Anything? A few types? A very restricted set which you have control over? Some classes you design in conjunction with the function foo? Given the latter, you could simple put something like
typedef boolean<true> has_bar_func;
into the types and then switch to different foo overloads based on that:
template <typename T>
void foo_impl(const T& t, boolean<true> /*has_bar_func*/);
template <typename T>
void foo_impl(const T& t, boolean<false> /*has_bar_func*/);
template <typename T>
void foo(const T& t) {
foo_impl( t, typename T::has_bar_func() );
}
Also, can the bar/baz function have just about any signature, is there a somewhat restricted set, or is there just one valid signature? If the latter, litb's (excellent) fallback idea, in conjunction with a meta-function employing sizeof might be a bit simpler. But this I haven't explored, so it's just a thought.
I think litb's solution works, but is overly complex. The reason is that he's introducing a function fallback::bar(...) which acts as a "function of last resort", and then goes to great lengths NOT to call it. Why? It seems we have a perfect behavior for it:
namespace fallback {
template<typename T>
inline void bar(T const& t, ...)
{
baz(t);
}
}
template<typename T>
void foo(T const& t)
{
using namespace fallback;
bar(t);
}
But as I indicated in a comment to litb's original post, there are many reasons why bar(t) could fail to compile, and I'm not certain this solution handles the same cases. It certainly will fail on a private bar::bar(T t)
If you're willing to limit yourself to Visual C++, you can use the __if_exists and __if_not_exists statements.
Handy in a pinch, but platform specific.
EDIT: I spoke too soon! litb's answer shows how this can actually be done (at the possible cost of your sanity... :-P)
Unfortunately I think the general case of checking "would this compile" is out of reach of function template argument deduction + SFINAE, which is the usual trick for this stuff. I think the best you can do is to create a "backup" function template:
template <typename T>
void bar(T t) { // "Backup" bar() template
baz(t);
}
And then change foo() to simply:
template <typename T>
void foo(const T& t) {
bar(t);
}
This will work for most cases. Because the bar() template's parameter type is T, it will be deemed "less specialised" when compared with any other function or function template named bar() and will therefore cede priority to that pre-existing function or function template during overload resolution. Except that:
If the pre-existing bar() is itself a function template taking a template parameter of type T, an ambiguity will arise because neither template is more specialised than the other, and the compiler will complain.
Implicit conversions also won't work, and will lead to hard-to-diagnose problems: Suppose there is a pre-existing bar(long) but foo(123) is called. In this case, the compiler will quietly choose to instantiate the "backup" bar() template with T = int instead of performing the int->long promotion, even though the latter would have compiled and worked fine!
In short: there's no easy, complete solution, and I'm pretty sure there's not even a tricky-as-hell, complete solution. :(
//default
//////////////////////////////////////////
template <class T>
void foo(const T& t){
baz(t);
}
//specializations
//////////////////////////////////////////
template <>
void foo(const specialization_1& t){
bar(t);
}
....
template <>
void foo(const specialization_n& t){
bar(t);
}
Are you not able to use full specialisation here (or overloading) on foo. By say having the function template call bar but for certain types fully specialise it to call baz?