Sending tags, variation template, universal link and missing const specifier

Please consider the following example (tag manager, variation template, perfect redirection, etc., all in one):

#include <iostream>
#include <utility>
#include <string>

struct A { };
struct B { };

void doIt(A&&, const std::string &) {
    std::cout << "A-spec" << std::endl;
}

template<typename T, typename... Args>
void doIt(T&&, Args&&...) {
    std::cout << "template" << std::endl;
}

template<typename T, typename... Args>
void fn(Args&&... args) {
    doIt(T{}, std::forward<Args>(args)...);
}

int main() {
    const std::string foo = "foo";
    std::string bar = "bar";
    fn<A>(foo);
    fn<A>(bar);
    fn<B>(foo);
}

In this case, the output is:

A-spec
template
template

The reason is quite obvious, it does not bother me.

What I would like to achieve is to call the first instance of the function doItin both cases, regardless of whether the string has a const specifier or not.
Of course, a possible solution is to define a new one doItwith the right prototype, in any case, I would like to know if there is another solution.

add_const, , - .
, const ?

, .
, , , , std::string. , ( ) A int const std::string &, B float, C ...
- , , - std::string, , .

+4
3

, , :

void doIt(A&&, const std::string &)
{
    std::cout << "A-spec" << std::endl;
}

template <typename T, typename... Args>
void doIt_template(T&&, Args&&...)
{
    std::cout << "template" << std::endl;
}

; , , :

template <typename T, typename... Args>
auto fn_impl(int, Args&&... args)
    -> decltype(doIt(T{}, std::forward<Args>(args)...), void())
{
    doIt(T{}, std::forward<Args>(args)...);
}

template <typename T, typename... Args>
void fn_impl(char, Args&&... args)
{
    doIt_template(T{}, std::forward<Args>(args)...);
}

:

template <typename T, typename... Args>
void fn(Args&&... args)
{
    fn_impl<T>(0, std::forward<Args>(args)...);
}

DEMO

+5

- , , .

- , Args... - , std::string:

template<typename... Args>
struct convertible_to_single_string {
    static std::true_type help (std::string);
    static std::false_type help (...);
    using type = decltype(help(std::declval<Args>()...));
    static constexpr auto value = type::value;
};

template<typename... Args>
std::enable_if_t<!convertible_to_single_string<Args...>::value, void> 
doIt(int, Args&&...) {
    std::cout << "template" << std::endl;
}

const char* - std::string. , , cv- , std::is_same<std::string, T>.

Live Demo

+4
template<class String,
  std::enable_if_t<std::is_same<std::decay_t<String>,std::string>{},int> =0
>
void doIt(int, String&&) {
  std::cout << "std::string" << std::endl;
}

, SFINAE, string.

, usimg. is_same is_convertible, , std::string.

, arg , , , .

+1

Source: https://habr.com/ru/post/1623918/


All Articles