LINUX.ORG.RU

История изменений

Исправление fsb4000, (текущая версия) :

Я надеюсь мне простят занудство, но в контексте решаемой ТС задачи действительно нужны шаблоны? Действительно это является наиболее рациональным решением?

Если нужно, чтобы метод f был не шаблонным, то можно перенести шаблон выше, но тогда нужно будет дублировать все остальные методы…

Как-то так: https://gcc.godbolt.org/z/vo77nez8c

В С++17, всё было бы проще из-за if constexpr

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
    if constexpr (has_double_multiply<T>(nullptr)) {
      return x * y;
    } else {
      return x;
    }
  }
};

https://gcc.godbolt.org/z/es7vYnaMW

А в С++20 можно бы сделать так:

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
      if constexpr(requires{x*y;}) {
        return x * y;
      }
      else {
          return x;
      }
  }
};

https://gcc.godbolt.org/z/1on9bKfTK

Или так

template <typename T> 
struct A {
  T x{};

  T f(double y) const requires(requires{x*y;}){
        return x * y;
  }

  T f(double y) const requires(!requires{x*y;}){
        return x;
  }
};

https://gcc.godbolt.org/z/r78a5Kr47

В 14 плюсах всё было бы как в 11, но просто чуток короче:

Вместо:

template <typename U = T,
          typename enable_if<!has_double_multiply<U>(nullptr), int>::type = 0>
  U f(double /*y*/) const {
    return x;
  }

было бы

template <typename U = T, enable_if_t<!has_double_multiply_v<U>, int> = 0>
  U f(double /*y*/) const {
    return x;
  }

https://gcc.godbolt.org/z/d39c8M9ax

И ещё одно :),

if constexpr настолько лучше чем то что было раньше, что компиляторы ввели его для всех стандартов, https://gcc.godbolt.org/z/h94K58z44 , чтобы использовать для реализации стандартной библиотеки в режиме С++11/С++14 или С++98. А SFINAE/tag dispatch выжигать из исходников где только можно :)

Скоро и на концепты заменят где удобнее, как компиляторы немного обновятся:

https://github.com/microsoft/STL/issues/602

https://github.com/microsoft/STL/issues/189

Исправление fsb4000, :

Я надеюсь мне простят занудство, но в контексте решаемой ТС задачи действительно нужны шаблоны? Действительно это является наиболее рациональным решением?

Если нужно, чтобы метод f был не шаблонным, то можно перенести шаблон выше, но тогда нужно будет дублировать все остальные методы…

Как-то так: https://gcc.godbolt.org/z/vo77nez8c

В С++17, всё было бы проще из-за if constexpr

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
    if constexpr (has_double_multiply<T>(nullptr)) {
      return x * y;
    } else {
      return x;
    }
  }
};

https://gcc.godbolt.org/z/es7vYnaMW

А в С++20 можно бы сделать так:

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
      if constexpr(requires{x*y;}) {
        return x * y;
      }
      else {
          return x;
      }
  }
};

https://gcc.godbolt.org/z/1on9bKfTK

Или так

template <typename T> 
struct A {
  T x{};

  T f(double y) const requires(requires{x*y;}){
        return x * y;
  }

  T f(double y) const requires(!requires{x*y;}){
        return x;
  }
};

https://gcc.godbolt.org/z/r78a5Kr47

В 14 плюсах всё было бы как в 11, но просто чуток короче:

Вместо:

template <typename U = T,
          typename enable_if<!has_double_multiply<U>(nullptr), int>::type = 0>
  U f(double /*y*/) const {
    return x;
  }

было бы

template <typename U = T, enable_if_t<!has_double_multiply_v<U>, int> = 0>
  U f(double /*y*/) const {
    return x;
  }

https://gcc.godbolt.org/z/d39c8M9ax

Исправление fsb4000, :

Я надеюсь мне простят занудство, но в контексте решаемой ТС задачи действительно нужны шаблоны? Действительно это является наиболее рациональным решением?

Если нужно, чтобы метод f был не шаблонным, то можно перенести шаблон выше, но тогда нужно будет дублировать все остальные методы…

Как-то так: https://gcc.godbolt.org/z/vo77nez8c

В С++17, всё было бы проще из-за if constexpr

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
    if constexpr (has_double_multiply<T>(nullptr)) {
      return x * y;
    } else {
      return x;
    }
  }
};

https://gcc.godbolt.org/z/es7vYnaMW

А в С++20 можно бы сделать так:

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
      if constexpr(requires{x*y;}) {
        return x * y;
      }
      else {
          return x;
      }
  }
};

https://gcc.godbolt.org/z/1on9bKfTK

Или так

template <typename T> 
struct A {
  T x{};

  T f(double y) const requires(requires{x*y;}){
        return x * y;
  }

  T f(double y) const requires(!requires{x*y;}){
        return x;
  }
};

https://gcc.godbolt.org/z/r78a5Kr47

Исходная версия fsb4000, :

Я надеюсь мне простят занудство, но в контексте решаемой ТС задачи действительно нужны шаблоны? Действительно это является наиболее рациональным решением?

Если нужно, чтобы метод f был не шаблонным, то можно перенести шаблон выше, но тогда нужно будет дублировать все остальные методы…

Как-то так: https://gcc.godbolt.org/z/vo77nez8c

В С++17, всё было бы проще из-за if constexpr

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
      if constexpr(has_double_multiply<T>(nullptr)) {
        return x * y;
      }
      else {
          return x;
      }
  }
};

https://gcc.godbolt.org/z/es7vYnaMW

А в С++20 можно бы сделать так:

template <typename T> 
struct A {
  T x{};

  T f(double y) const {
      if constexpr(requires{x*y;}) {
        return x * y;
      }
      else {
          return x;
      }
  }
};

https://gcc.godbolt.org/z/1on9bKfTK

Или так

template <typename T> 
struct A {
  T x{};

  T f(double y) const requires(requires{x*y;}){
        return x * y;
  }

  T f(double y) const requires(!requires{x*y;}){
        return x;
  }
};

https://gcc.godbolt.org/z/r78a5Kr47