Какова логика ключевого слова "using" в C++?
какова логика ключевого слова "using" в C++?
Он используется в разных ситуациях, и я пытаюсь найти
если все это имеет что-то общее и есть причина
почему ключевое слово" using " используется как таковое.
using namespace std; // to import namespace in the current namespace
using T = int; // type alias
using SuperClass::X; // using super class methods in derived class
1 ответ:
в C++11,
usingдля сайта при использованииtype aliasидентиченtypedef.7.1.3.2
имя typedef также может быть введено с помощью объявления псевдонима. Этот идентификатор после ключевого слова using становится typedef-name и необязательный атрибут-спецификатор-сл следующим идентификатором принадлежит к этому typedef-имя. Он имеет ту же семантику, как если бы это было введено спецификатором typedef. В частности, это не так определять новый тип, и он не должен отображаться в идентификаторе типа.
Бьярне Страуструп приводит практический пример:
typedef void (*PFD)(double); // C style using PF = void (*)(double); // using plus C-style type using P = [](double)->void; // using plus suffix return type, syntax error using P = auto(double)->void // Fixed thanks to DyPPre-C++11, the
usingключевое слово может привести функции-члены в область действия. В C++11 Теперь вы можете сделать это для конструкторов (другой пример Bjarne Stroustrup):class Derived : public Base { public: using Base::f; // lift Base's f into Derived's scope -- works in C++98 void f(char); // provide a new f void f(int); // prefer this f to Base::f(int) using Base::Base; // lift Base constructors Derived's scope -- C++11 only Derived(char); // provide a new constructor Derived(int); // prefer this constructor to Base::Base(int) // ... };
Бен Войт дает довольно вескую причину для обоснования не введения нового ключевого слова или нового синтаксиса. Стандарт хочет избежать ломать старый код как можно больше. Вот почему в документах предложения вы увидите такие разделы, как
Impact on the Standard,Design decisionsи как они могут повлиять на старого кода. Есть ситуации, когда предложение кажется действительно хорошей идеей, но может не иметь тяги, потому что это было бы слишком сложно реализовать, слишком запутанно или противоречило бы старому коду.
вот старая бумага от 2003 года n1449. Обоснование, по-видимому, связано с шаблонами. Предупреждение: есть могут быть опечатки из-за копирования из PDF.
сначала рассмотрим игрушечный пример:
template <typename T> class MyAlloc {/*...*/}; template <typename T, class A> class MyVector {/*...*/}; template <typename T> struct Vec { typedef MyVector<T, MyAlloc<T> > type; }; Vec<int>::type p; // sample usageфундаментальная проблема с этой идиомой, и главный мотивирующий факт для этого предложения является то, что идиома вызывает параметры шаблона появляются в неразрешимом контексте. То есть, это будет невозможно вызов функции foo ниже без явного указания шаблона аргументы.
template <typename T> void foo (Vec<T>::type&);Итак, синтаксис немного уродливый. Мы бы предпочли избежать вложенных
::typeМы бы предпочли что-то вроде следующего:template <typename T> using Vec = MyVector<T, MyAlloc<T> >; //defined in section 2 below Vec<int> p; // sample usageобратите внимание, что мы специально избегаем термина "шаблон typedef" и intr приведите новый синтаксис, включающий пару "using " и"=", чтобы помочь избежать путаница: мы не определяем здесь какие-либо типы, мы вводим синоним (т. е. псевдоним) для абстракции типа-id (т. е. тип выражение) с использованием параметров шаблона. Если параметры шаблона используются в выводимых контексты в выражении типа then whenever псевдоним шаблона используется для формирования шаблона-id, значения соответствующие параметры шаблона могут быть выведены – подробнее об этом будет следовать. В любом случае, теперь можно писать универсальные функции которые работают на
Vec<T>в выводимом контексте, и синтаксис также улучшилось. Например, мы могли бы переписать foo как:template <typename T> void foo (Vec<T>&);мы подчеркиваем здесь, что одной из основных причин для предложения псевдонимы шаблонов было так, что аргумент дедукции и призыв к
foo(p)будет иметь успех.
в документе n1489 объясняет, почему
usingвместоtypedef:было предложено (повторно) использовать ключевое слово typedef-как это сделано в paper [4] - чтобы ввести псевдонимы шаблонов:
template<class T> typedef std::vector<T, MyAllocator<T> > Vec;эта нотация имеет преимущество использования ключевого слова, уже известного введите псевдоним типа. Впрочем, это тоже отображает несколько дезавуации, среди которых путаница с использованием ключевого слова, известного введите псевдоним для имени типа в контексте, где псевдоним делает не обозначить тип, а шаблон;
Vecне является псевдонимом для a введите, и не следует принимать за typedef-name. ИмяVec- это имя для семьиstd::vector< [bullet] , MyAllocator< [bullet] > >- где пуля является заполнителем для имени типа. Следовательно, мы не предлагайте синтаксис "typedef". С другой стороны предложениеtemplate<class T> using Vec = std::vector<T, MyAllocator<T> >;можно читать / интерпретировать как: отныне я буду использовать
Vec<T>как a синонимstd::vector<T, MyAllocator<T> >. С этим чтением, новый синтаксис для сглаживания кажется достаточно логичным.я думаю, что здесь делается важное различие,псевдоним es вместо типs. Еще одна цитата из того же документа:
объявление псевдонима-это объявление, а не определение. Кличка- объявление вводит имя в декларативная область в качестве псевдонима для типа, указанного в правой части объявления. Этот ядро этого предложения касается псевдонимов имен типов, но очевидно, что нотация может быть обобщена для обеспечения альтернативных вариантов написания пространства имен-сглаживание или именование набора перегруженных функций (см. ✁ 2.3 для дальнейшего обсуждения). [мое Примечание: В этом разделе обсуждается, как может выглядеть этот синтаксис и причины, по которым он не является частью предложения.] можно отметить что грамматика производство псевдоним-заявление является приемлемым в любом месте оператор typedef объявление или определение псевдонима пространства имен является приемлемым.
резюме, для роли
using:
- шаблонные псевдонимы (или шаблонные typedefs, первый предпочтительнее namewise)
- псевдонимы пространства имен (т. е.
namespace PO = boost::program_optionsиusing PO = ...эквивалент)- , - говорится в документе
A typedef declaration can be viewed as a special case of non-template alias-declaration. Это эстетическое изменение, и считается идентичным в этом случай.- ввод чего-то в область действия (например,
namespace stdв глобальную область), функции-члены, наследующие конструкторыэто не может используется для:
int i; using r = i; // compile-errorвместо этого:
using r = decltype(i);именование набора перегрузок.
// bring cos into scope using std::cos; // invalid syntax using std::cos(double); // not allowed, instead use Bjarne Stroustrup function pointer alias example using test = std::cos(double);
Comments