Alexey S. Larionov
Alexey S. Larionov

Reputation: 7937

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?

Upvotes: 1

Views: 73

Answers (2)

Davis Herring
Davis Herring

Reputation: 40013

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.

Upvotes: 1

Nicol Bolas
Nicol Bolas

Reputation: 474036

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.

Upvotes: 5

Related Questions