Pourquoi éviter les amis ou comment j'ai perdu tous mes avantages

Salut, Habr.


Il y a quelques jours, je suis tombé sur ce tweet:



En bref: une fois de plus, en C ++, ils ont trouvé une sorte de merde qui y apparaissait elle-même, émergente-convergente, comme la boue d'une courte histoire de science-fiction que j'ai lue dans mon enfance, qui a surgi accidentellement dans les égouts urbains et est devenue un solvant organique universel.


Voyons cela, car ce ne sera pas long (selon le texte de la norme, je n'ai pas sauté plus de quelques heures). Et amusant, les liens vers Standard sont toujours amusants.


Voici tout le code:


#include <cstdio>

class tag;

template<class>
struct type { friend constexpr auto get(type); };

template<class TKey, class TValue>
struct set { friend constexpr auto get(TKey) { return TValue{}; } };

void foo() {            // never called
  if constexpr(false) { // never true
    if (false) {        // never true
        constexpr auto call = [](auto value) { std::printf("called %d", value); };
        void(set<type<tag>, decltype(call)>{});
    }
  }
}

int main() {
  get(type<tag>{})(42); // prints called 42
}

.


class tag;

, .


template<class>
struct type { friend constexpr auto get(type); };

type. , get - .


, (13.9.1/1) type<T> T? ( , argument-dependent lookup, !) get(T) (9.8.1.2/3, 13.9.1/4), (6.2/2.1).


template<class TKey, class TValue>
struct set { friend constexpr auto get(TKey) { return TValue{}; } };

set. , , get - .


, set<K, V> K, V? get(K), (6.2/2).


void foo() {
  if constexpr(false) {
    if (false) {
        constexpr auto call = [](auto value) { std::printf("called %d", value); };
        void(set<type<tag>, decltype(call)>{});
    }
  }
}

, if (false) , , :


void foo() {
  if constexpr(false) {
    constexpr auto call = [](auto value) { std::printf("called %d", value); };
    set<type<tag>, decltype(call)>{};
  }
}

, if constexpr , . ?


if constexpr : 8.5.1/2. :


If the value of the converted condition is false, the first substatement is a discarded statement

, call set — discarded statement. .


:


During the instantiation of an enclosing templated entity, if the condition is not value-dependent after its instantiation, the discarded substatement (if any) is not instantiated.

discarded statement, , . false, , value-dependent, «». «enclosing template entity», enclosing entity — foo, . , , , if constexpr .


. , type<tag>, get(type<tag>) , ADL, get type<tag> ( 9.8.1.2/3). set<type<tag>, decltype(call)>, get(type<tag>), type<tag>. decltype(call), call , C++20 (7.5.5.1/13), . main get(type<tag>{}), get ADL. , call, , 42.


.


, — discarded statement enclosing template entity. , void foo() template<typename> void foo(),


-
#include <cstdio>

class tag;

template<class>
struct type { friend constexpr auto get(type); };

template<class TKey, class TValue>
struct set { friend constexpr auto get(TKey) { return TValue{}; } };

template<typename>
void foo() {
  if constexpr(false) { // never true
    if (false) {        // never true
        constexpr auto call = [](auto value) { std::printf("called %d", value); };
        void(set<type<tag>, decltype(call)>{});
    }
  }
}

int main() {
  foo<int>();
  get(type<tag>{})(42); // prints called 42
}

:


prog.cc:23:3: error: function 'get' with deduced return type cannot be used before it is defined
  get(type<tag>{})(42); // prints called 42
  ^
prog.cc:6:37: note: 'get' declared here
struct type { friend constexpr auto get(type); };
                                    ^

, C++ - — , ( -), ( SFINAE, detector idiom ). , - C++?


, , C++. , — , - . — - , , - - template , . , , chaotic evil. — , , , , .


, . - C++14, C++11, 03.


? :


Defining a friend function in a template, then referencing that function later provides a means of capturing and retrieving metaprogramming state. This technique is arcane and should be made ill-formed.
Notes from the May, 2015 meeting:
CWG agreed that such techniques should be ill-formed, although the mechanism for prohibiting them is as yet undetermined.

, — , .


— , ?


, !

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


All Articles