C ++: Как перегрузить pow для пользовательского типа? - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть пользовательский тип T, для которого я хотел бы придать смысл понятию степени pow(T1, T2).

Затем в шаблонном коде я хотел бы иметь возможность написать std::pow(a, b), а затем, если a, b окажется double или float, он делает то, что всегда делает, и если они оказываются типа T, тогда я хочу вызвать мою перегрузку.

Как мне это сделать?

Я мог бы дать своему типу pow -оператор, но как мне тогда различить std::pow и pow -оператор?

Ответы [ 3 ]

0 голосов
/ 02 ноября 2018

Вы не можете добавлять имена в std пространства имен. Единственное, что вы можете сделать, это добавить специализации. Если вы готовы игнорировать это (многие люди так делают!), Самым простым решением было бы добавить эту перегрузку в пространство имен std.

Полностью совместимым решением было бы добавить перегрузку к одному из видимых пространств имен, и тогда, когда вы планируете вызвать одну из доступных pow версий, сделайте это:

using std::pow;

pow(a, b);

Чем, если случится, что a и b относятся к типам, поддерживаемым std::pow, он будет вызван, иначе ваша перегрузка будет.

0 голосов
/ 02 ноября 2018

Вы не можете напрямую перегрузить std::pow. Стандарт запрещает добавлять новые перегрузки к функциям в пространстве имен std.

Что вы можете сделать, так это использовать ADL для выбора нужной функции pow, аналогичной тому, как люди часто добавляют swap перегрузки:

namespace my_namespace {

struct my_type {
    explicit my_type(double d) : my_num{d} {}
    double my_num;
};

my_type pow(const my_type& a, const my_type& b) {
    std::cout << "my_namespace::pow(my_type, my_type) called\n";
    return my_type{std::pow(a.my_num, b.my_num)};
}

}

template <typename T>
void foo() {
    using std::pow;
    pow(T{2}, T{10});
}

int main() {
    foo<float>(); // calls std::pow
    foo<my_namespace::my_type>(); // calls my_namespace::pow
}

Live Demo

0 голосов
/ 02 ноября 2018

Вы не можете перегружать функцию в пространстве имен std. Типичным решением для этого является объявление вашей функции в том же пространстве имен, что и пользовательский тип, такой как

namespace my_code
{
    struct foo {};

    foo pow(foo base, int power)
    {
        // code here
    }
}

И затем в вашей функции, где вы используете pow, вы добавляете using std::pow. Это позволяет вам затем написать свой код как

void bar()
{
    using std::pow;
    //...
    auto a = pow(10,3);
    //...
    auto b = pow(foo{}, 3);

}

и строка pow(10,3) выберет версию функции std, в то время как pow(foo, 3) найдет вашу перегрузку через зависимый от аргумента поиск .

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