0

Я ищу советы о том, как реализовать (максимум т.е.) функция для типа данных пользовательского который также работает со скалярными типами, как float специализированной «макс». Тип данных Я пишу это обертка для вектора (в конце концов, вектор SIMD из четырех поплавков, а не std::vector), и я хочу, чтобы обеспечить max функции сравнением двух векторов и возвращает новый вектор, максимум каждого элемента , Это отличается от std::max, который использует оператор сравнения, но концепция одинаков.C++ - Как специализировать настраиваемый тип для std :: max без перегрузки операторов сравнения?

Проблема в том, что у меня есть общая функция, называемая do_max(T x, T y), которая применяет max к входам. Мне нужна эта функция работать как для скалярных флоат входов (например do_max<float>(0.1f, 0.2f)) и мой вектор класса (например, do_max<MyVector>(v0, v1)).

Обратите внимание, что перегрузка операторов сравнения MyVector не является опцией, потому что я использую те, у которых с SIMD-интерфейсами совершенно разные: они создают целочисленный вектор, содержащий 1, 0, -1 для каждого сравнения элементов, а не возвращают логическое результат.

код у меня ниже не компилируется, если вы закомментировать float f0 = ... строки:

// compile with: g++ -std=c++11 max.cc -o max 
#include <algorithm> 
#include <vector> 

class MyVector { 
public: 
    MyVector(float x0, float x1, float x2, float x3) : storage_ { x0, x1, x2, x3 } {}; 

    friend MyVector max(MyVector lhs, const MyVector & rhs); 

private: 
    std::vector<float> storage_; 
}; 

MyVector max(MyVector lhs, const MyVector & rhs) { 
    for (size_t i = 0; i < lhs.storage_.size(); ++i) { 
    lhs.storage_[i] = std::max(lhs.storage_[i], rhs.storage_[i]); 
    } 
    return lhs; 
} 

template<typename T> 
T do_max(const T & x, const T & y) { 
    // if this is std::max then it won't compile for MyVector 
    return max(x, y); 
} 

int main(int argc, char * argv[]) { 

    MyVector v0 { 0.1, 0.2, 0.3, 0.4 }; 
    MyVector v1 { 0.4, 0.3, 0.2, 0.1 }; 

    MyVector v2 = do_max(v0, v1); 

    // Comment out the following line to successfully compile. 
    // However I'd like this to work for scalar types too: 
    float f0 = do_max(0.1f, 0.2f); 

    return 0; 
} 

У меня есть чувство, что я нужен способ, чтобы сделать эту max функции решимость std::max для скалярных типов, и мои специализированное max Функция друга для типа MyVector.

Как я определить функцию максимального, которая работает таким образом? Лучше ли забыть о std::max и использовать мою собственную функцию max, которая специализируется на MyVector, а также обеспечивает реализацию для таких скалярных типов, как float?

Предпосылкой этого является то, что я реализует путь данных, я надеюсь, будет работать как с MyVector и скалярных типов (как параметризованные типа во время компиляции). У меня уже есть арифметическая работа, однако решение для max будет использоваться с другими функциями, такими как min, exp, pow.

ответ

7

Классический решение:

template<typename T> 
T do_max(const T & x, const T & y) { 
    using std::max; 
    return max(x, y); 
} 

Аргумент-Dependent Lookup находит ваш max, для float этого не происходит, и вы получите std::max<float>.

+0

Спасибо, что работает для моего примера. – meowsqueak

+0

Знаете ли вы, почему это не удается, если я заменил 'return max (x, y)' на 'return max (x, y)'? В этом случае, это выглядит как компилятор решает это как вызов 'станд :: макс (х, у)' и не с некорректными операндами к '' <оператору, когда '' do_max конкретизируются. Я не понимаю, почему изменение типа параметра на 'max' изменило бы это поведение. – meowsqueak

+1

Ваша функция не является шаблоном? max - это явное создание шаблона. – MSalters

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