2017-02-19 20 views
3
#include <string> 
#include <type_traits> 

class C 
{ 
    static auto func() { return std::string("hello"); } 
    static_assert(std::is_same<decltype(func()), std::string>::value, ""); 
}; 

Ни GCC, ни Clang не принимают это, заявив, что func используется до его определения. Зачем?Почему этот встроенный метод с выведенным типом возврата еще не определен?

Изменение выведенного auto типа возврата в std::string заставляет его работать.

+2

встраиваемая функция есть, как если бы вы написали их право * после * конец определения класса, так что в точке 'static_assert' , функция еще не определена. –

+0

@KerrekSB, но с изменением типа возвращаемого значения на явный, он компилирует штраф – Danra

+0

Несомненно, но вся точка 'auto' заключается в том, чтобы вывести тип из определения ... –

ответ

3

Конструкция decltype создает объявленный тип идентификатора или выражения. Когда func объявлен с типом возврата, то тип выражения вызова func() известен и все работает так, как ожидалось.

Однако, когда func объявлен с возвратным типом заполнителем auto, то объявление funcзависит от его определения, поэтому типа func, и, следовательно, выражения func(), не известно, пока эта функция не была определены.

Когда вы определяете функцию члена класса inline в определении класса, это значит, что определение должно появляться сразу после окончания определения класса (то есть тела функций могут ссылаться на имена, которые лексически объявлены позже в определении класса). Следствием этого и семантики auto является то, что ваша функция auto func на самом деле не полностью объявила до конца определения класса, и поэтому тип func() не может быть известен до этого момента.

+0

«Когда вы определяете функцию члена класса inline в определении класса, это значит, что определение должно появляться сразу после окончания определения класса» - Есть ли для этого хорошее обоснование? – Danra

+0

@ Danra: Общие ожидания пользователей, чтобы иметь возможность обращаться к членам класса? –

+0

Не будет ли это работать, если встроенные функции были добавлены к определению класса? Это, в свою очередь, позволит использовать их выведенный тип возврата. – Danra

1

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

В финальном релизе, это должно быть равно нулю стоимость:

#include <string> 
#include <type_traits> 
#include <iostream> 

struct C 
{ 
    static auto func() { 
     check_same(); 
     return std::string("hello"); 
    } 

private: 

    static void check_same() 
    { 
     static_assert(std::is_same<decltype(func()), std::string>::value, ""); 
    } 
}; 

int main() 
{ 
    std::cout << C::func() << '\n'; 
} 
определения

 Смежные вопросы

  • Нет связанных вопросов^_^