Match template unconditionally - c++

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.

Related

Call less constrained functionally equivalent function

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

C++ template argument of unknown type

Suppose we want to write a function which is supposed to get a value as a template parameter (for, say, efficiency reasons), but we don't know in advance the type of the parameter we're expecting. It is possible to implement it as
template<typename T, T val>
func() { cout << val; }
However, it is not fun to call such a function
func<int, 5>()
is it possible to rewrite func s.t. we can call it in the following way?
func<5>()
A solution that mostly depends on your actual function is to define it as it follows:
template<typename T>
constexpr void func(T val) { }
Then invoke it as f(5) and have the template parameter deduced from the parameter of the function itself.
Otherwise, in C++14, you cannot avoid using the pattern template<typename T, T value>.
It is the same pattern used by the Standard Template Library, see as an example the definition of std::integral_constant.
A possible solution that mitigates (maybe) the boilerplate is based on the use of a struct, as an example:
template<typename T>
struct S {
template<T value>
static void func() {}
};
You can the do something like this:
using IntS = S<int>;
// ....
IntS::func<5>();
With the upcoming revision C++17, you will manage to do it as it follows:
template<auto value>
void func() {}
This can be invoked as f<5>(), that is what you are looking for..

"What happened to my SFINAE" redux: conditional template class members?

I'm new to writing template metaprogramming code (vs. just reading it). So I'm running afoul of some noob issues. One of which is pretty well summarized by this non-SO post called "What happened to my SFINAE?", which I will C++11-ize as this:
(Note: I gave the methods different names only to help with my error diagnosis in this "thought experiment" example. See #R.MartinhoFernandes's notes on why you wouldn't actually choose this approach in practice for non-overloads.)
#include <type_traits>
using namespace std;
template <typename T>
struct Foo {
typename enable_if<is_pointer<T>::value, void>::type
valid_if_pointer(T) const { }
typename disable_if<is_pointer<T>::value, void>::type
valid_if_not_pointer(T) const { }
};
int main(int argc, char * argv[])
{
int someInt = 1020;
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
return 0;
}
#Alf says what happened to the SFINAE is "It wasn't there in the first place", and gives a suggestion that compiles, but templates the functions instead of the class. That might be right for some situations, but not all. (For instance: I'm specifically trying to write a container that can hold types that may or may not be copy-constructible, and I need to flip methods on and off based on that.)
As a workaround, I gave this a shot...which appears to work correctly.
#include <type_traits>
using namespace std;
template <typename T>
struct FooPointerBase {
void valid_if_pointer(T) const { }
};
template <typename T>
struct FooNonPointerBase {
void valid_if_not_pointer(T) const { }
};
template <typename T>
struct Foo : public conditional<
is_pointer<T>::value,
FooPointerBase<T>,
FooNonPointerBase<T> >::type {
};
int main(int argc, char * argv[])
{
int someInt = 1020;
#if DEMONSTRATE_ERROR_CASES
Foo<int*>().valid_if_not_pointer(&someInt);
Foo<int>().valid_if_pointer(304);
#else
Foo<int*>().valid_if_pointer(&someInt);
Foo<int>().valid_if_not_pointer(304);
#endif
return 0;
}
But if this is not broken (is it?), it's certainly not following a good general methodology for how to turn on and off methods in a templated class based on sniffing the type for traits. Is there a better solution?
Firstly, C++11 did not carry forward boost's disable_if. So if you're going to transition boost code, you'll need to use enable_if with a negated condition (or redefine your own disable_if construct).
Secondly, for SFINAE to reach in and apply to the method level, those methods must be templates themselves. Yet your tests have to be done against those templates' parameters...so code like enable_if<is_pointer<T> will not work. You can finesse this by making some template argument (let's say X) default to be equal to T, and then throw in a static assertion that the caller has not explicitly specialized it to something else.
This means that instead of writing:
template <typename T>
struct Foo {
typename enable_if<is_pointer<T>::value, void>::type
valid_if_pointer(T) const { /* ... */ }
typename disable_if<is_pointer<T>::value, void>::type
valid_if_not_pointer(T) const { /* ... */ }
};
...you would write:
template <typename T>
struct Foo {
template <typename X=T>
typename enable_if<is_pointer<X>::value, void>::type
valid_if_pointer(T) const {
static_assert(is_same<X,T>::value, "can't explicitly specialize");
/* ... */
}
template <typename X=T>
typename enable_if<not is_pointer<X>::value, void>::type
valid_if_not_pointer(T) const {
static_assert(is_same<X,T>::value, "can't explicitly specialize");
/* ... */
}
};
Both are now templates and the enable_if uses the template parameter X, rather than T which is for the whole class. It's specifically about the substitution that happens whilst creating the candidate set for overload resolution--in your initial version there's no template substitution happening during the overload resolution.
Note that the static assert is there to preserve the intent of the original problem, and prevent someone being able to compile things like:
Foo<int>().valid_if_pointer<int*>(someInt);
The way I see it you don't want SFINAE here. SFINAE is useful to pick between different templated overloads. Basically, you use it to help the compiler pick between template <typename Pointer> void f(Pointer); and template <typename NotPointer> void f(NotPointer);.
That's not what you want here. Here, you have two functions with different names, not two overloads of the same. The compiler can already pick between template <typename Pointer> void f(Pointer); and template <typename NotPointer> void g(NotPointer);.
I'll give an example to explain why I think SFINAE is not only unnecessary, but undesirable here.
Foo<int> not_pointer;
Foo<int*> pointer;
not_pointer.valid_if_pointer(); // #1
not_pointer.valid_if_not_pointer(); // #2
pointer.valid_if_pointer(); // #3
pointer.valid_if_not_pointer(); // #4
Now, let's say you managed to get this working with SFINAE. Attempting to compile this piece of code will yield errors on lines #1 and #4. Those errors will be something along the lines of "member not found" or similar. It may even list the function as a discarded candidate in overload resolution.
Now, let's say you didn't do this with SFINAE, but with static_assert instead. Like this:
template <typename T>
struct Foo {
void valid_if_pointer(T) const {
static_assert(std::is_pointer<T>::value, "valid_if_pointer only works for pointers");
// blah blah implementation
}
void valid_if_not_pointer(T) const {
static_assert(!std::is_pointer<T>::value, "valid_if_not_pointer only works for non-pointers");
// blah blah implementation
}
};
With this you'll get errors on the same line. But you'll get extremely short and useful errors. Something people have been asking of compiler writers for years. And it's now at your doorstep :)
You get the same thing: errors on both cases, except you get a much better one without SFINAE.
Also note that, if you didn't use static_assert at all and the implementation of the functions was only valid if given pointers or non-pointers, respectively, you would still get errors on the appropriate lines, except maybe nastier ones.
TL;DR: unless you have two actual template functions with the same name, it's preferable to use static_assert instead of SFINAE.

Handling of references in C++ templates

I currently have a function template, taking a reference, that does something in essence equivalent to:
template <typename T>
void f(T& t)
{
t = T();
}
Now, I can call:
int a;
f(a);
To initialize my variable a.
I can even do:
std::vector<int> a(10);
f(a[5]);
However, this will fail:
std::vector<bool> a(10);
f(a[5]);
The reason being a[5] returns an object with reference semantic, but not a reference. So I need to be able to write:
template <typename T>
void f(T a)
{
a = T();
}
But if I add this new template and try to compile the first example (with int), I obtain the following error:
test_multi_tmpl.cc: In function ‘int main()’:
test_multi_tmpl.cc:20: error: call of overloaded ‘f(int&)’ is ambiguous
test_multi_tmpl.cc:6: note: candidates are: void f(T&) [with T = int]
test_multi_tmpl.cc:12: note: void f(T) [with T = int]
Any ideas how to solve this? I wouldn't like to overload f just for std::vector<bool>::reference as this construct might appears in other places ...
I think specialising f for std::vector<bool>::reference is your only option.
Note that using std::vector<bool> is probably a bad idea in the first place (the std::vector<bool> specialisation is deprecated for future versions of the c++ language) so you could just use std::deque<bool> instead.
I'm not sure whether you already know about this...
The specialization std::vector is not really a STL container because it does not meet the necessary requirements. In particular, it's not possible to created proxied containers that satisfy the STL concepts because of the reference semantics (you can't fake a reference). Check this article for more information. (Also, as Autopulated mentioned there should be a compiler directive to provide control over std::vector in the future C++ Standard.)
A simple workaround that could solve your problem is by overloading function f for this particular type (and others if they appear and are not many). Notice that this is an overload and not an specialization. You might also wanna check this for why not specialize function templates.
void f(std::vector<bool>::reference t)
{
/* ... */
}
There are two ways to do this, one is, as you suggest, specialize for std::vector<bool>::reference. The other is by using type-traits dispatching.
template <class T>
void f (T& t) {
f_impl(t, is_reference_wrapper_type<T>());
}
template <class T>
void f_impl(T& t, mpi::false_) {
t = T();
}
template <class T>
void f_impl(T& t, mpi::true_) {
// do nothing, or voodoo here
}
Note the code above is un-tested and there would be more complex means of dispatching based on a trait -- or a set of traits -- in this situation.
This would also mean that you would need to implement is_reference_wrapper_type like so:
template <class T>
struct is_reference_wrapper_type : mpi::false_ {};
template <>
struct is_reference_wrapper_type<std::vector<bool>::reference> : mpi::true_ {};
Using traits or template specialization would make it work.

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?