Условное включение / исключение членов данных внутри шаблонов классов - PullRequest
2 голосов
/ 21 февраля 2009

Я хочу оптимизировать свои классы Vector и Matrix (точнее, шаблоны классов) с использованием инструкций SIMD и встроенных функций компилятора. Я хочу оптимизировать только для случая, когда тип элемента "float". Использование SIMD инструкций требует прикосновения к элементам данных. Поскольку я не хочу беспокоиться о том, чтобы поддерживать два отдельных класса, я хочу иметь возможность включать / отключать некоторые элементы данных в зависимости от типа параметра шаблона. Другое преимущество этого подхода, в случае его применимости, заключается в том, что я могу использовать тот же код из общего случая для функций, для которых я не хочу писать специализацию. Поэтому, чего я хочу добиться в псевдокоде:

template< typename T >
class Vector3 {
    if type( T ) == float:
        union {
            __m128 m128;
            struct {
                float x, y, z, pad;
            };
        };
   else
       T x, y, z;
   endif
};

Я знаю, что условное включение функций-членов возможно с помощью Boost.enable_if или аналогичных средств. Однако я ищу условное включение членов данных. Как всегда, ваша помощь очень ценится. Другие действительные предложения также приветствуются.

Спасибо.

1 Ответ

4 голосов
/ 21 февраля 2009

Одно решение, которое приходит на ум, - это частично специализированные шаблоны, которые опубликовал Мартин Йорк, но с изюминкой.

Я бы порекомендовал специальную структуру content_type для предоставления типа макета, например:

// content for non float types
template<typename T>
struct content_type {
   typedef typename T member_type;
   member_type x,y,z;
   member_type& X { return x; }
   // ...
   // if access to optional members is needed, better use CT_ASSERT or similar
   member_type& Pad { char assert_error_no_pad_here[0]; }
};

// content for float types
struct content_type<float> {
   typedef typename float member_type;
   member_type x, y, z, pad;
   member_type& X { return x; }
   // ...
   member_type& Pad { return pad; }
};

template<typename T>
class Vector3 {
    typedef typename content_type<T> layout_type;
    typedef typename content_type<T>::member_type member_type;

    layout_type _content;

  public:
    member_type& X { return _content.X(); }
    memmber_type& Pad { return _content.Pad(); }
};

// or maybe, if memory layout is not important, just inherit (watch for virtual members)
template<typename T>
class Vector3 : public content_type<T> {
    typedef typename content_type<T> layout_type;
    typedef typename content_type<T>::member_type member_type;
};

Преимущество в том, что вам нужно написать Vector3 со всей его логикой только один раз.

Для корректной работы необходим компилятор сравнительно недавнего времени (MSVC> 7, gcc> 3)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...