Должен ли я использовать 'border: none' или 'border: 0'?

Что вам нужно сделать, так это то, что препроцессор генерирует данные отражения в полях. Эти данные могут храниться как вложенные классы.

Во-первых, чтобы упростить и очистить его в препроцессоре, мы будем использовать типизированное выражение. Типированное выражение - это просто выражение, которое помещает тип в круглые скобки. Поэтому вместо записи int x вы напишете (int) x. Вот несколько полезных макросов, которые помогут с типизированными выражениями:

#define REM(...) __VA_ARGS__
#define EAT(...)

// Retrieve the type
#define TYPEOF(x) DETAIL_TYPEOF(DETAIL_TYPEOF_PROBE x,)
#define DETAIL_TYPEOF(...) DETAIL_TYPEOF_HEAD(__VA_ARGS__)
#define DETAIL_TYPEOF_HEAD(x, ...) REM x
#define DETAIL_TYPEOF_PROBE(...) (__VA_ARGS__),
// Strip off the type
#define STRIP(x) EAT x
// Show the type without parenthesis
#define PAIR(x) REM x

Далее мы определяем макрос REFLECTABLE для генерации данных о каждом поле (плюс само поле). Этот макрос будет вызываться следующим образом:

REFLECTABLE
(
    (const char *) name,
    (int) age
)

Таким образом, используя Boost.PP , мы перебираем каждый аргумент и генерируем такие данные:

// A helper metafunction for adding const to a type
template
struct make_const
{
    typedef T type;
};

template
struct make_const
{
    typedef typename boost::add_const::type type;
};


#define REFLECTABLE(...) \
static const int fields_n = BOOST_PP_VARIADIC_SIZE(__VA_ARGS__); \
friend struct reflector; \
template \
struct field_data {}; \
BOOST_PP_SEQ_FOR_EACH_I(REFLECT_EACH, data, BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__))

#define REFLECT_EACH(r, data, i, x) \
PAIR(x); \
template \
struct field_data \
{ \
    Self & self; \
    field_data(Self & self) : self(self) {} \
    \
    typename make_const::type & get() \
    { \
        return self.STRIP(x); \
    }\
    typename boost::add_const::type & get() const \
    { \
        return self.STRIP(x); \
    }\
    const char * name() const \
    {\
        return BOOST_PP_STRINGIZE(STRIP(x)); \
    } \
}; \

Что это такое, генерирует константу fields_n, которая является числом отражаемых полей в классе. Затем он специализируется на field_data для каждого поля. Он также поддерживает класс reflector, поэтому он может обращаться к полям, даже если они являются частными:

struct reflector
{
    //Get field_data at index N
    template
    static typename T::template field_data get_field_data(T& x)
    {
        return typename T::template field_data(x);
    }

    // Get the number of fields
    template
    struct fields
    {
        static const int n = T::fields_n;
    };
};

Теперь, чтобы перебирать поля, мы используем шаблон посетителя. Мы создаем диапазон MPL от 0 до количества полей и получаем доступ к данным поля по этому индексу. Затем он передает данные поля посетителю, предоставленному пользователю:

struct field_visitor
{
    template
    void operator()(C& c, Visitor v, I)
    {
        v(reflector::get_field_data(c));
    }
};


template
void visit_each(C & c, Visitor v)
{
    typedef boost::mpl::range_c::n> range;
    boost::mpl::for_each(boost::bind(field_visitor(), boost::ref(c), v, _1));
}

Теперь на момент истины мы все вместе. Вот как мы можем определить класс Person, который можно отразить:

struct Person
{
    Person(const char *name, int age)
        :
        name(name),
        age(age)
    {
    }
private:
    REFLECTABLE
    (
        (const char *) name,
        (int) age
    )
};

Вот обобщенная функция print_fields, использующая данные отражения для итерации по полям:

struct print_visitor
{
    template
    void operator()(FieldData f)
    {
        std::cout << f.name() << "=" << f.get() << std::endl;
    }
};

template
void print_fields(T & x)
{
    visit_each(x, print_visitor());
}

Пример использования print_fields с отражаемым классом Person:

int main()
{
    Person p("Tom", 82);
    print_fields(p);
    return 0;
}

Какие выходы:

name=Tom
age=82

И вуаля, мы только что реализовали отражение в C ++, менее чем в 100 строк кода.

497
задан SilverHorn 15 August 2011 в 23:21
поделиться

5 ответов

Оба действительны. Выбор за вами.

Я предпочитаю границу : 0 , потому что она короче; Мне так легче читать. Вы можете найти нет более разборчивым. Мы живем в мире очень мощных постпроцессоров CSS, поэтому я рекомендую вам использовать все, что вы предпочитаете, а затем запускать его через «компрессор». Здесь нет священной войны, за которую стоит сражаться.

Тем не менее, если вы пишете весь рабочий CSS от руки, я утверждаю - несмотря на ворчание в комментариях - не помешает учитывать пропускную способность.Использование border: 0 позволит сэкономить бесконечно малую полосу пропускания. Само по себе это очень мало, но если вы сделаете счетом каждый байт , вы сделаете свой сайт быстрее.

Спецификации CSS2 находятся здесь . Они расширены в CSS3, но не имеют к этому никакого отношения.

'border'
    Value:      [ <border-width> || <border-style> || <'border-top-color'> ] | inherit
    Initial:    see individual properties
    Applies to:     all elements
    Inherited:      no
    Percentages:    N/A
    Media:      visual
    Computed value:     see individual properties 

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

429
ответ дан 22 November 2019 в 22:33
поделиться

Самый легкий Способ удалить границу с css

border: 0;
0
ответ дан 22 November 2019 в 22:33
поделиться

Я использую:

border: 0;

From 8.5.4 в CSS 2.1 :

'border'

Значение: [ || <стиль границы> || <'border-top-color'>] | inherit

Итак, любой из ваших методов выглядит нормально.

6
ответ дан 22 November 2019 в 22:33
поделиться

Они эквивалентны по эффекту, указывая на разные ярлыки:

border: 0;
//short for..
border-width: 0;

А другой...

border: none;
//short for...
border-style: none;

Оба работают, просто выберите один и идите с ним :)

147
ответ дан 22 November 2019 в 22:33
поделиться

Как уже говорили другие, оба действительны и помогут. Я не уверен на 100%, что они идентичны. Если у вас происходит каскадирование стилей, то теоретически они могут давать разные результаты, поскольку они эффективно переопределяют разные значения.

Например. Если вы установите "border: none;" а затем, позже, есть два разных стиля, которые переопределяют ширину и стиль границы, тогда один будет что-то делать, а другой - нет.

В следующем примере и в IE, и в firefox первые два тестовых div не имеют границы. Однако вторые два отличаются тем, что первый div во втором блоке является простым, а второй div во втором блоке имеет пунктирную границу средней ширины.

Итак, хотя оба они действительны, вам, возможно, придется следить за своими стилями, если они сильно каскадированы и тому подобное, как я думаю.

<html>
<head>
<style>
div {border: 1px solid black; margin: 1em;}
.zerotest div {border: 0;}
.nonetest div {border: none;}

div.setwidth {border-width: 3px;}
div.setstyle {border-style: dashed;}

</style>
</head>
<body>

<div class="zerotest">
<div class="setwidth">
"Border: 0" and "border-width: 3px"
</div>
<div class="setstyle">
"Border: 0" and "border-style: dashed"
</div>
</div>

<div class="nonetest">
<div class="setwidth">
"Border: none" and "border-width: 3px"
</div>
<div class="setstyle">
"Border: none" and "border-style: dashed"
</div>
</div>

</body>
</html>
41
ответ дан 22 November 2019 в 22:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: