如何声明 SFINAE 类?

问题描述 投票:0回答:3

有些事情对我来说不太顺利。这是声明一个只接受浮点模板参数的类的方法吗?

template <typename T, swift::enable_if<std::is_floating_point<T>::value> = nullptr>
  class my_float;

我无法在此类之外定义方法。无法编译,不知道为什么

c++ c++11 templates sfinae
3个回答
2
投票

您还可以使用

static_assert
毒害无效类型。

template <typename T>
class my_float {
  static_assert(std::is_floating_point<T>::value,
    "T is not a floating point type");
  // . . .
};

我认为这更直接一些。

使用其他任何一种方法,例如

template <typename T, bool = std::is_floating_point<T>::value>
class my_float;

template <typename T> class my_float<T, true> { /* . . . */ };

my_float<int,true>
是一个有效的表达式。我并不是说这是一个不好的方法,但如果你想避免这种情况,你必须封装
my_float<typename,bool>
在另一个模板中,以避免暴露
bool
模板参数。


1
投票

嗯...不完全是SFINAE...但也许,使用模板专业化?如下?

template <typename T, bool = std::is_floating_point<T>::value>
class my_float;

template <typename T>
class my_float<T, true>
 {
   // ...
 };

如果你真的想使用SFINAE,你可以写

template <typename T,
   typename = typename std::enable_if<std::is_floating_point<T>::value>::type>
class my_float
 {
   // ...
 };

或者也(观察示例中没有的指针)

template <typename T,
   typename std::enable_if<std::is_floating_point<T>::value>::type * = nullptr>
class my_float  // ------------------------------------------------^
 {
 };

--编辑--

按照 Yakk 的建议(谢谢!),您可以混合 SFINAE 和模板专业化,为不同类型的群体开发不同版本的类。

例如以下

my_class

template <typename T, typename = void>
class my_class;

template <typename T>
class my_class<T,
   typename std::enable_if<std::is_floating_point<T>::value>::type>
 {
   // ...
 };

template <typename T>
class my_class<T,
   typename std::enable_if<std::is_integral<T>::value>::type>
 {
   // ...
 };

开发有两个版本(两个不同的部分特化),第一个版本用于浮点类型,第二个版本用于整数类型。并且可以轻松扩展。


0
投票

确实,这样的东西对我有用(感谢SU3的回答)。

template<typename T, bool B = false>
struct enable_if {};

template<typename T>
struct enable_if<T, true> {
    static const bool value = true;
};

template<typename T, bool b = enable_if<T,is_allowed<T>::value>::value >
class Timer{ void start(); };

template<typename T, bool b>
void Timer<T,b>::start()
{ \* *** \*}

我发布这个答案是因为我不想使用部分专业化,而只想定义外部类的行为。

一个完整的可行示例:

typedef std::integral_constant<bool, true> true_type;
typedef std::integral_constant<bool, false> false_type;

struct Time_unit {
};

struct time_unit_seconds : public Time_unit {
    using type = std::chrono::seconds;
};

struct time_unit_micro : public Time_unit {
    using type = std::chrono::microseconds;
};

template<typename T, bool B = false>
struct enable_if {
};

template<typename T>
struct enable_if<T, true> {
    const static bool value = true;
};

template<typename T,
        bool b = enable_if<T,
                std::is_base_of<Time_unit,
                        T>::value
        >::value>
struct Timer {
    int start();
};

template<typename T, bool b>
int Timer<T, b>::start() { return 1; }

int main() {
    Timer<time_unit_seconds> t;
    Timer<time_unit_micro> t2;
//    Timer<double> t3; does not work !

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.