Да:
@import url("base.css");
Примечание:
@import
правило должно предшествовать все другие правила (кроме эти @charset
правило); и @import
требуют дополнительных запросов к серверу. Совокупный CSS в один файл для предотвращения нескольких Запросов HTTP. Таким образом, скопируйте содержание base.css
и special.css
в base-special.css
и ссылка [только 117]).
В 2008, не все браузеры поддерживали @import
(см. Совместимость браузера ).
Если вы немного измените свое заявление, вы получите совершенно другую историю
template <class T>
void foo(T::type& v);
Это уже не однозначно. Он может объявить переменную типа void
, которая инициализируется побитовым выражением AND
. Вся декларация будет шаблонной. Конечно, все это семантически бессмысленно, но синтаксически все в порядке.
Появление единственного const
синтаксически делает его однозначным, но это слишком большая зависимость от контекста, чтобы заставить это работать в компиляторе. Он должен помнить, что он читает const
или любую другую подобную вещь, и когда он анализирует T::type
после того, как ему нужно будет помнить, принять это имя как тип. Это также привело бы к дальнейшему раздутию и без того непростого стандарта.
Давайте снова изменим объявление вашей функции
template <class T>
void foo(const T::type);
Даже появление const
не обеспечивает однозначного анализа. Должно ли это быть объявление функции с неназванным параметром, или это должно быть объявление функции с недопустимым именем параметра, которое пропускает свой тип? Имя параметра анализируется с помощью declarator-id
, который также может быть квалифицированным именем. Таким образом, здесь const
будет принадлежать спецификаторам типа, в то время как T::type
будет анализироваться компилятором как имя параметра, в отсутствие typename
. Это тоже полная чушь, , но синтаксически верна .
В случае имен базового класса поиск имен сам по себе гласит, что нетипичные имена игнорируются. Таким образом, вы получаете опущение typename
бесплатно: имя, которое поиск по имени дает более высокоуровневым модулям компилятора, либо относится к типу, либо поиск по имени даст ошибку.
Я написал статью с часто задаваемыми вопросами о Где поставить «шаблон» и «имя типа» на зависимые имена .
Во-первых, я не думаю, что когда-либо имелось намерение провести четкое и точное различие между ситуациями, когда разрешены только типы названий (например, имя базового класса), и ситуациями, где также допускаются нетипичные объекты (например, выражения ). Я бы сказал, что контекст имени базового класса был выделен по какой-то другой причине.
Во-вторых, не совсем правильно говорить, что в объявлениях параметров функции каждая сущность обязательно является именем типа. Вы можете объявить параметр следующим образом
template <class T>
void foo(const T::type& v[T::value]);
Конечно, грамматика в этом случае явно диктует, что type
должно быть именем типа, а value
должно быть значением. Тем не менее, компилятор может выяснить это после синтаксического анализа объявления, в то время как я полагаю, что идея typename
была введена, чтобы помочь компилятору фактически запустить правильный синтаксический анализ. анализ кода, т. е. различие должно быть доступно до синтаксического анализа, как вход в синтаксический анализ. Это различие может оказать глубокое влияние на интерпретацию кода.