Mengapa menghindari teman, atau bagaimana saya kehilangan semua kelebihan saya

Hai, Habr.


Beberapa hari yang lalu saya menemukan tweet ini:



Singkatnya: sekali lagi di C ++ mereka menemukan semacam omong kosong yang muncul di sana sendiri, muncul-konvergen, seperti lendir dari satu cerita fiksi ilmiah pendek yang saya baca di masa kecil saya, yang secara tidak sengaja muncul di selokan perkotaan dan tumbuh menjadi pelarut organik universal.


Mari kita mengetahuinya, karena tidak akan lama (menurut teks Standar saya melompat tidak lebih dari beberapa jam). Dan kesenangan, tautan ke Standar selalu menyenangkan.


Ini seluruh kodenya:


#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/id472780/


All Articles