2012-02-27 2 views
4

у меня есть:decltype (* & fun) странно?

#include <type_traits> 
#include <stdio.h> 

void f() { printf("foo\n"); } 

int main() 
{ 
    printf("%d %d %d\n", 
    std::is_same<decltype(*&f),decltype(f)>::value, 
    std::is_function<decltype(*&f)>::value, 
    std::is_function<decltype(f)>::value); 
    (*&f)(); 
    return 0; 
} 

, который дает

0 0 1 
foo 

на г ++ 4.6.1 и 4.7.0.

Может кто-нибудь объяснить это мне?

+0

Я уверен, что '* & f' является ссылочным типом. –

+0

Бинго! std :: remove_reference <...> делает трюк! – smilingthax

ответ

13

Важно отметить, что decltype имеет два значения: он может быть использован, чтобы найти объявленный тип (отсюда его название) в сущности, или он может быть использован для проверки в выражения. Я использую сущность здесь свободно и не имею в виду ни один термин Стандарта, но, просто говоря, это может быть переменная, функция или (как ни странно, на мой взгляд) членский доступ. Тип, который возвращается, когда рассматривается выражение чаще, чем не отличается от типа самого выражения, таким образом:

int i; 
void foo(); 
struct { int i; } t; 

static_assert(std::is_same<decltype(i),  int>::value,  ""); 
static_assert(std::is_same<decltype(foo), void()>::value, ""); 
static_assert(std::is_same<decltype(t.i), int>::value,  ""); 

static_assert(std::is_same<decltype((i)), int&>::value,  ""); 
static_assert(std::is_same<decltype((foo)), void(&)()>::value, ""); 
static_assert(std::is_same<decltype((t.i)), int&>::value,  ""); 

Обратите внимание, как это работает для функций, и, следовательно, в вашем случае decltype(*&f) одно и то же как decltype((f)), а не decltype(f).

+1

Tgis - половина правды. тип выражения (f) не относится к ссылочному типу. выражение не имеет ссылочного типа. –

+0

@ JohannesSchaub-litb Вы правы, конечно. Я не знаю, что это за отказ от ответственности - я думаю, что моя маленькая выдумка не * упрощает определение «decltype». Это, однако, упрощение того, как взаимодействуют категории значений, ссылки и ссылочные типы. –

+0

@Potatoswatter Я откат, потому что я разработал свой ответ, чтобы не описать полное поведение 'decltype'. Достаточно (IMO) указать, что 'decltype (name)' отличается от 'decltype ((name))' для ответа на вопрос. Добавление более подробной информации было бы более уместным для вопроса о внутренней работе 'decltype'. Тем не менее, я решил, что соответствующий отказ от ответственности должен указывать на то, что фрагменты предназначены только для иллюстрации * некоторых * поведения 'decltype'. –