Warum Freunde meiden oder wie ich alle meine Vorteile verloren habe?

Hallo Habr.


Vor ein paar Tagen bin ich auf diesen Tweet gestoßen:



Kurz gesagt: Wieder einmal fanden sie in C ++ eine Art Mist, der dort selbst auftauchte, emergent-konvergent, wie Schleim aus einer kurzen Science-Fiction-Geschichte, die ich in meiner Kindheit gelesen hatte und die versehentlich in städtischen Abwasserkanälen entstand und zu einem universellen organischen Lösungsmittel heranwuchs.


Lassen Sie es uns herausfinden, da es nicht lange dauern wird (gemäß dem Text des Standards bin ich nicht länger als ein paar Stunden gesprungen). Und Spaß, Links zu Standard machen immer Spaß.


Hier ist der gesamte 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/de472780/


All Articles