poor man's instrumentation
От: dilmah США  
Дата: 24.01.12 01:32
Оценка:
озадачился вопросом, можно ли придумать простой кусок кода, который сможет отличить где он (этот кусок) находится -- в обычном методе или в статическом?
Re: poor man's instrumentation
От: zaufi Земля  
Дата: 24.01.12 05:59
Оценка:
Здравствуйте, dilmah, Вы писали:

D>озадачился вопросом, можно ли придумать простой кусок кода, который сможет отличить где он (этот кусок) находится -- в обычном методе или в статическом?


речь о compile-time или run-time?
Re[2]: poor man's instrumentation
От: dilmah США  
Дата: 24.01.12 06:39
Оценка:
Z>речь о compile-time или run-time?

run-time.

Но я уже по-моему понял, что то что я хотел не получится.

Идея такая -- у меня есть длинная строчка на шелле, которая может примитивно инструментировать C++ код -- вставить на входы, выходы из функций, на throw -- вставить отладочную печать.
Все делается примитивно, ни о каком точном разборе C++ грамматики речь не идет, но тот код который у меня есть он обрабатывает нормально.

Захотелось сделать крошечное усовершенствование -- на входе в метод логировать еще адрес объекта, но так как методы бывают статические, то захотелось вставить нечто, что будет печатать адрес this в обычном методе, но не будет в статическом. Но видимо это невозможно, потому что this там фигурировать обязан, а он даст ошибку компиляции в статическом методе..

То есть нужен более глобокий анализ кода, а это уже выходит за рамки длинной строки на шелле.
Re[3]: poor man's instrumentation
От: rumit7  
Дата: 24.01.12 07:59
Оценка: 10 (1)
Здравствуйте, dilmah, Вы писали:


Z>>речь о compile-time или run-time?


D>run-time.


D>Но я уже по-моему понял, что то что я хотел не получится.


D>Идея такая -- у меня есть длинная строчка на шелле, которая может примитивно инструментировать C++ код -- вставить на входы, выходы из функций, на throw -- вставить отладочную печать.

D>Все делается примитивно, ни о каком точном разборе C++ грамматики речь не идет, но тот код который у меня есть он обрабатывает нормально.

D>Захотелось сделать крошечное усовершенствование -- на входе в метод логировать еще адрес объекта, но так как методы бывают статические, то захотелось вставить нечто, что будет печатать адрес this в обычном методе, но не будет в статическом. Но видимо это невозможно, потому что this там фигурировать обязан, а он даст ошибку компиляции в статическом методе..


D>То есть нужен более глобокий анализ кода, а это уже выходит за рамки длинной строки на шелле.


Используя возможности C++0x можно наверное как-то так.
Re[4]: poor man's instrumentation
От: Masterkent  
Дата: 24.01.12 10:43
Оценка: 12 (2)
rumit7:

R>Используя возможности C++0x можно наверное как-то так.


Это не возможности C++0x, а баги GNU C++ Такая программа должна вывести три единицы. Тип нестатической функции-члена без cv-квалификаторов ничем не отличается от типа обычной функции.

typedef void F();

struct X
{
    F f; // OK, declared type of f is void()
};

void X::f() {} // OK

int main() {}
Re[5]: poor man's instrumentation
От: rumit7  
Дата: 24.01.12 13:09
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>rumit7:


R>>Используя возможности C++0x можно наверное как-то так.


M>Это не возможности C++0x, а баги GNU C++


Ну тогда так!?, хотя теперь имя функции-члена класса нужно указывать полностью как "class_name::func_name". Как я понял это из-за вот этого:

C++0x, N3290, 5.3.1

4. A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed
in parentheses. [ Note: that is, the expression &(qualified-id), where the qualified-id is enclosed in
parentheses, does not form an expression of type “pointer to member.” Neither does qualified-id, because
there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to
member function” as there is from an lvalue of function type to the type “pointer to function” (4.3). Nor is
&unqualified-id a pointer to member, even within the scope of the unqualified-id’s class. — end note ]

Re[6]: poor man's instrumentation
От: Ops Россия  
Дата: 24.01.12 16:45
Оценка:
Здравствуйте, rumit7, Вы писали:
Ну, 3290 — это не стандарт, а лишь последний драфт, и кенту я больше верю. Если он согласится, что был не прав — поверю.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[7]: poor man's instrumentation
От: rumit7  
Дата: 24.01.12 16:54
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Здравствуйте, rumit7, Вы писали:

Ops>Ну, 3290 — это не стандарт, а лишь последний драфт, и кенту я больше верю. Если он согласится, что был не прав — поверю.

А я нигде и не ставлю под сомнение компетенцию Masterkent-а! Наоборот, я ему благодарен за то, что указал мне на мою ошибку! Да и вообще, круто что на форуме есть такие люди!

А в последнем посте я просто предложил другой (надеюсь в этот раз правильный) вариант реализации..
Re[6]: poor man's instrumentation
От: Masterkent  
Дата: 24.01.12 17:58
Оценка:
rumit7:

R>Ну тогда так!?, хотя теперь имя функции-члена класса нужно указывать полностью как "class_name::func_name".


Мне не ясен смысл этого подхода. Если мы можем ручками прописывать class_name::func_name, то что нам мешает вместо этого прописать принадлежность функции к нестатической в каком-либо виде? Тем более, что игры с указателями на функции плохо сочетаются с перегрузкой функций. Я так понял, что ТС хочет что-то вроде макроса, который автоматически (без каких-то подсказок) может распознать, где он находится, и, соответственно, раскрыться либо в this, либо во что-то ещё. Я сомневаюсь в том, что такое возможно реализовать, но судить наверняка не берусь.
Re[7]: poor man's instrumentation
От: Masterkent  
Дата: 24.01.12 17:59
Оценка:
Ops:

Ops>Ну, 3290 — это не стандарт, а лишь последний драфт


Насколько мне известно, по техническому содержанию N3290/N3291, C++11 и N3337 ничем не отличаются. Нормативные правила в N3290 и C++11 совпадают с точностью до опечаток
Re[5]: poor man's instrumentation
От: Masterkent  
Дата: 24.01.12 20:03
Оценка:
Masterkent:

M>rumit7:


R>>Используя возможности C++0x можно наверное как-то так.


M>Это не возможности C++0x, а баги GNU C++ Такая программа должна вывести три единицы. Тип нестатической функции-члена без cv-квалификаторов ничем не отличается от типа обычной функции.


Я забыл, что на использование non-static member functions имеются жёсткие ограничения:

5.1.1/12:

An id-expression that denotes a non-static data member or non-static member function of a class can only be used:

— as part of a class member access (5.2.5) in which the object expression refers to the member’s class [Footnote: This also applies when the object expression is an implicit (*this) (9.3.1).] or a class derived from that class, or

— to form a pointer to member (5.3.1), or

— in a mem-initializer for a constructor for that class or for a class derived from that class (12.6.2), or

— in a brace-or-equal-initializer for a non-static data member of that class or of a class derived from that class (12.6.2), or

— if that id-expression denotes a non-static data member and it appears in an unevaluated operand.

9.3.1/3:

When an id-expression (5.1) that is not part of a class member access syntax (5.2.5) and not used to form a pointer to member (5.3.1) is used in a member of class X in a context where this can be used (5.1.1), if name lookup (3.4) resolves the name in the id-expression to a non-static non-type member of some class C, and if either the id-expression is potentially evaluated or C is X or a base class of X, the id-expression is transformed into a class member access expression (5.2.5) using (*this) (9.3.2) as the postfix-expression to the left of the . operator.

5.2.5/4:

If E2 is declared to have type “reference to T,” then E1.E2 is an lvalue; the type of E1.E2 is T. Otherwise, one of the following rules applies.

[...]

— If E2 is a (possibly overloaded) member function, function overload resolution (13.3) is used to determine whether E1.E2 refers to a static or a non-static member function.

  — If it refers to a static member function and the type of E2 is “function of parameter-type-list returning T”, then E1.E2 is an lvalue; the expression designates the static member function. The type of E1.E2 is the same type as that of E2, namely “function of parameter-type-list returning T”.

  — Otherwise, if E1.E2 refers to a non-static member function and the type of E2 is “function of parameter-type-list cv ref-qualifieropt returning T”, then E1.E2 is a prvalue. The expression designates a non-static member function. The expression can be used only as the left-hand operand of a member function call (9.3). [ Note: Any redundant set of parentheses surrounding the expression is ignored (5.1). —end note ] The type of E1.E2 is “function of parameter-type-list cv returning T”.

[...]

По всей видимости, эти ограничения делают данную программу некорректной.
Re: poor man's instrumentation
От: rm822 Россия  
Дата: 25.01.12 02:45
Оценка:
Здравствуйте, dilmah, Вы писали:

D>озадачился вопросом, можно ли придумать простой кусок кода, который сможет отличить где он (этот кусок) находится -- в обычном методе или в статическом?

можно. на аспектах.
http://www.aspectc.org
я этой фигней пользовался еще в 2005м примерно и остался доволен
Re[2]: poor man's instrumentation
От: dilmah США  
Дата: 25.01.12 03:28
Оценка:
R>http://www.aspectc.org
R>я этой фигней пользовался еще в 2005м примерно и остался доволен

как оно в сравнении с clang?
Re[3]: poor man's instrumentation
От: rm822 Россия  
Дата: 25.01.12 04:05
Оценка:
D>как оно в сравнении с clang?
хз, даже не в курсе что это такое
Re[7]: poor man's instrumentation
От: rumit7  
Дата: 25.01.12 06:21
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>rumit7:


R>>Ну тогда так!?, хотя теперь имя функции-члена класса нужно указывать полностью как "class_name::func_name".


M>Мне не ясен смысл этого подхода. Если мы можем ручками прописывать class_name::func_name, то что нам мешает вместо этого прописать принадлежность функции к нестатической в каком-либо виде?


Из-за того, что в предложенном мною методе необходимо квалифицировать имя функции именем класса, полезность его в данном случае конечно сомнительна. Но решать конечно ТС. Я со своей стороны постарался помочь — имеющимся у меня в арсенале знаниями, умением и временем.

M>Тем более, что игры с указателями на функции плохо сочетаются с перегрузкой функций.


В моем решении я основывался на том, что указатель на функцию-член и указатель на статическую функцию класса имеют разный тип. Вот здесь немного про это сказано, хотя и в несколько другом контексте:

C++0x, N3290, 5.3.1

6. The address of an overloaded function (Clause 13) can be taken only in a context that uniquely determines
which version of the overloaded function is referred to (see 13.4). [ Note: since the context might determine
whether the operand is a static or non-static member function, the context can also affect whether the
expression has type “pointer to function” or “pointer to member function.
” — end note ]


M>Я так понял, что ТС хочет что-то вроде макроса, который автоматически (без каких-то подсказок) может распознать, где он находится, и, соответственно, раскрыться либо в this, либо во что-то ещё. Я сомневаюсь в том, что такое возможно реализовать, но судить наверняка не берусь.


У ТС имеется "строчка на шелле, которая может примитивно инструментировать C++ код -- вставить на входы, выходы из функций, на throw -- вставить отладочную печать.". О всех возможностях данного шелла остается только догадываться, но возможно она умеет узнавать полное имя функции (в формате class_name::func_name), и тогда предложенный мною метод можно использовать для функций определенных за пределами класса (как известно там статик функции класса очень даже похожи на функции-члены).
Re[6]: poor man's instrumentation
От: rumit7  
Дата: 25.01.12 06:31
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Masterkent:


M>Я забыл, что на использование non-static member functions имеются жёсткие ограничения:


M>[...]


M>5.2.5/4:

M>

If E2 is declared to have type “reference to T,” then E1.E2 is an lvalue; the type of E1.E2 is T. Otherwise, one of the following rules applies.

M>[...]

M>  — Otherwise, if E1.E2 refers to a non-static member function and the type of E2 is “function of parameter-type-list cv ref-qualifieropt returning T”, then E1.E2 is a prvalue. The expression designates a non-static member function. The expression can be used only as the left-hand operand of a member function call (9.3). [ Note: Any redundant set of parentheses surrounding the expression is ignored (5.1). —end note ] The type of E1.E2 is “function of parameter-type-list cv returning T”.

M>[...]

M>По всей видимости, эти ограничения делают данную программу некорректной.

Осмелюсь с Вами здесь не согласиться, т.к. в своем коде использую указатель на функцию-член класса только в контексте "тип аргумента функции". И нигде в стандарте я не нашел пункта, запрещающий мне передавать в функцию указатель на функцию-член класса.
Re[8]: poor man's instrumentation
От: rumit7  
Дата: 25.01.12 08:07
Оценка:
Здравствуйте, rumit7, Вы писали:

R>Здравствуйте, Masterkent, Вы писали:


M>>rumit7:


[...]

M>>Тем более, что игры с указателями на функции плохо сочетаются с перегрузкой функций.


R>В моем решении я основывался на том, что указатель на функцию-член и указатель на статическую функцию класса имеют разный тип.


Следовательно, функцию check_f, из приведенного мною выше кода, можно перегрузить по указателю на функцию-член и указателю на статическую функцию класса.

C++0x, N3290, 13.Overloading

1 When two or more different declarations are specified for a single name in the same scope, that name is said
to be overloaded. By extension, two declarations in the same scope that declare the same name but with
different types
are called overloaded declarations.
[...]


Смотрим какие есть ограничения на перегрузку:

C++0x, N3290, 13.1 Overloadable declarations

1 Not all function declarations can be overloaded. Those that cannot be overloaded are specified here.

2 Certain function declarations cannot be overloaded:
— Function declarations that differ only in the return type cannot be overloaded.
— Member function declarations with the same name and the same parameter-type-list cannot be over-
loaded if any of them is a static member function declaration [...]
— Member function declarations with the same name and the same parameter-type-list as well as mem-
ber function template declarations with the same name, the same parameter-type-list, and the same
template parameter lists cannot be overloaded if any of them, but not all, have a ref-qualifier
[...].


Пока всё нормально (?). Идем дальше и читаем, что такое указатель на статическую функцию класса:

C++0x, N3290, 3.9.2 Compound types

1 Compound types can be constructed in the following ways:
[...]
pointers to non-static [50] class members, which identify members of a given type within objects of a given class.
[...]

[50] Static class members are objects or functions, and pointers to them are ordinary pointers to objects or functions.


Дальше читаем про указатель на не статическую функцию-член класса:

C++0x, N3290, 8.3.3 Pointers to members

Note: See also 5.3 and 5.5. The type “pointer to member” is distinct from the type “pointer”, that is, a
pointer to member is declared only by the pointer to member declarator syntax, and never by the pointer
declarator syntax.


Таким образом, вроде с перегрузкой в моем случае всё в норме. Буду благодарен, если укажете на ошибки..
Re[7]: poor man's instrumentation
От: Masterkent  
Дата: 25.01.12 08:10
Оценка:
rumit7:

R>Здравствуйте, Masterkent, Вы писали:


M>>Masterkent:


M>>Я забыл, что на использование non-static member functions имеются жёсткие ограничения:


M>>[...]


M>>5.2.5/4:

M>>

If E2 is declared to have type “reference to T,” then E1.E2 is an lvalue; the type of E1.E2 is T. Otherwise, one of the following rules applies.

M>>[...]

M>>  — Otherwise, if E1.E2 refers to a non-static member function and the type of E2 is “function of parameter-type-list cv ref-qualifieropt returning T”, then E1.E2 is a prvalue. The expression designates a non-static member function. The expression can be used only as the left-hand operand of a member function call (9.3). [ Note: Any redundant set of parentheses surrounding the expression is ignored (5.1). —end note ] The type of E1.E2 is “function of parameter-type-list cv returning T”.

M>>[...]

M>>По всей видимости, эти ограничения делают данную программу некорректной.

R>Осмелюсь с Вами здесь не согласиться, т.к. в своем коде использую указатель на функцию-член класса только в контексте "тип аргумента функции". И нигде в стандарте я не нашел пункта, запрещающий мне передавать в функцию указатель на функцию-член класса.


Я говорил про твой первый вариант с decltype. Мне поначалу показалось, что он должен бы печатать три единицы, но потом я вспомнил про вышеуказанные ограничения, из-за которых такое применение decltype незаконно.
Re[9]: poor man's instrumentation
От: Masterkent  
Дата: 25.01.12 08:23
Оценка: 2 (1)
rumit7:

R>Здравствуйте, rumit7, Вы писали:


R>>Здравствуйте, Masterkent, Вы писали:


M>>>rumit7:


R>[...]


M>>>Тем более, что игры с указателями на функции плохо сочетаются с перегрузкой функций.


[...]

R>Таким образом, вроде с перегрузкой в моем случае всё в норме. Буду благодарен, если укажете на ошибки..


Тут я имел в виду трудности с перегрузкой проверяемой функции:
http://liveworkspace.org/code/62239c0ab3c4aee5f86333d57d2a9f7e

Аналогично с шаблонами:
http://liveworkspace.org/code/599591af34e05ff644a3c94edfff1864
Re[10]: poor man's instrumentation
От: rumit7  
Дата: 25.01.12 09:16
Оценка:
Здравствуйте, Masterkent, Вы писали:

M>Тут я имел в виду трудности с перегрузкой проверяемой функции:

M>http://liveworkspace.org/code/62239c0ab3c4aee5f86333d57d2a9f7e

M>Аналогично с шаблонами:

M>http://liveworkspace.org/code/599591af34e05ff644a3c94edfff1864

Спасибо!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.