Предотвращение конфликтов перегрузки оператора шаблона для чисел с плавающей точкой и не с плавающей запятой в первом аргументе оператора - PullRequest
0 голосов
/ 30 мая 2020

У меня есть ситуация, когда мой оператор модуля шаблона отлично работает между типами float и integer-i sh. Насколько я помню, есть способ сделать так, чтобы он выбирал более конкретный c, а не более широкий, но я не могу найти или вспомнить, как это сделать.

В основном у меня есть 2 метода, которые сталкиваются (ошибка переопределения).

Я пытаюсь получить специализированную перегрузку оператора модуля, которая будет использоваться, когда его тип (T_COORDS) - float , более широкий, когда он не плавает.

Специализированный (обратите внимание, он использует математическую функцию fmod):

template <size_t N
    , enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0, bool> = false>
friend Coords operator % (const Coords<float,C_COORDS,N_COORDS>& coords0, const auto (& coords1)[N])
{
  Coords<float,C_COORDS,N_COORDS> result = coords0;
  for (int i=0; i < C_COORDS*N_COORDS; i++)
      result.coords[i] = fmod(result.coords[i], coords1[i%N]);
  return result;
}

Более широкий (обратите внимание, что он использует стандартный модуль упругости):

template <std::size_t N
    , std::enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0
    , bool> = false>
friend Coords operator % (const Coords<T_COORDS,C_COORDS,N_COORDS>& coords0, const auto (& coords1)[N])
{
  Coords<T_COORDS,C_COORDS,N_COORDS> result = coords0;
  for (int i=0; i < C_COORDS*N_COORDS; i++)
      result.coords[i] %= coords1[i%N];
  return result;
}

Эти перегрузки включены в определение класса Template:

template <class T_COORDS, size_t C_COORDS, size_t N_COORDS>
class Coords {
public:

  T_COORDS coords[C_COORDS*N_COORDS];

  // (body in here)

};

Ответы [ 3 ]

1 голос
/ 30 мая 2020

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

#include <type_traits>
#include <iostream>
template <class T>
void func(){
    constexpr static bool isFloat = std::is_floating_point<T>::value;//static in classes
    if (isFloat) std::cout << "f\n";//u can use fmod() here
    else std::cout << "i\n";//use regular % here
}
int main(){
    func<int>();
    func<double>();
}
1 голос
/ 30 мая 2020

Я бы оставил только одну из этих перегрузок, но изменил ее для l oop на это:

for (int i=0; i < C_COORDS*N_COORDS; i++)
    result.coords[i] = my_mod(result.coords[i], coords1[i%N]);

После определения my_mod следующим образом (во внешней области):

template <typename T>
T my_mod(const T& x, const T& y) { return x % y; }

float my_mod(float x, float y) { return fmod(x, y); }
// maybe define it for double as well
1 голос
/ 30 мая 2020

T_COORDS - это параметр шаблона класса, а не параметр шаблона функции, что означает, что он не имеет значения для частичного упорядочивания, поскольку более общая функция в любом случае создается с помощью T_COORDS=float, и поэтому он точно такой же, как float один. Однако вы можете отключить эту функцию из разрешения перегрузки, используя тот факт, что она уже имеет некоторые enable_if условия, которые зависят от непосредственного контекста:

template <std::size_t N
        , std::enable_if_t<N != 0 && N <= C_COORDS*N_COORDS && N % C_COORDS == 0
                           && !std::is_same<T_COORDS, float>{}
                           // ~~~~~~~~~~~~^
        , bool> = false>
friend Coords operator %(const Coords<T_COORDS, C_COORDS, N_COORDS>& coords0
                       , const auto (& coords1)[N]);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...