Is there a way to use SFINAE to determine if a non-primary non-member function is declared?

I am trying to answer this question using SFINAE and decltype. To summarize, the poster wants to use a function that acts differently depending on whether another function is declared in the compilation module (it is declared sooner or later of the corresponding function).

I tried the following:

auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {
    cout << "Using some_function_1" << endl;
    some_function_1();
}

void some_function_2_impl(long) {
    cout << "Not using some_function_1" << endl;
}

void some_function_2() {
    return some_function_2_impl(0);
}   

However, I get this error message:

main.cpp:4:60: error: 'some_function_1' was not declared in this scope
 auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {

That’s the whole point, I thought, I don’t want the overload to some_function_2_implbe determined because it some_function_1does not exist.

I thought that maybe SFINAE requires the templates to work, so I tried the following (this can help indicate that I do not fully know what I'm doing here):

template <int foo>
auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {
    cout << "Using some_function_1" << endl;
    some_function_1();
}

template <int foo>
void some_function_2_impl(long) {
    cout << "Not using some_function_1" << endl;
}

However, now I get the following error:

main.cpp:5:60: error: there are no arguments to 'some_function_1' that 
depend on a template parameter, so a declaration of 'some_function_1'
must be available [-fpermissive]
 auto some_function_2_impl(int) -> decltype(some_function_1(), void()) {

?

+4
1

, , , ADL .

ADL . , .

, .

- :

template<class T, class...Ts>
struct first_two_match : std::false_type{};
template<class T, class...Ts>
struct first_two_match<T,T,Ts...>:std::true_type{}; // for standard compliance: If the only Ts... that match Ts... is nothing, program ill-formed.
struct secret_type_tag {};
template<class...Ts,
  std::enable_if_t<
    (sizeof...(Ts)==0) || first_two_match<secret_tag_type,Ts...>{}
  >* =nullptr
>
secret_type_tag some_function_1(Ts&&...);

template<bool b>
using bool_t=std::integral_constant<bool, b>;
static const auto some_function_defined = bool_t<
  !std::is_same<secret_tag_type, decltype( some_function_1() )>{}
>;

some_function_defined std::true_type, some_function_1, some_function_1(Ts&&...). some_function_1(Ts&&...) , "" ( 0 ).

, , , .

, some_function_1 , some_function_defined . .

+4

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


All Articles