我如何申报SFINAE课程?

时间:2017-12-31 20:46:30

标签: c++ c++11 templates sfinae

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

    RaycastHit hit = new RaycastHit();
    Physics.Raycast(touch.position, touch.position, out hit);
    if (hit.collider == GameObject.FindGameObjectWithTag("Sphere0"))
    {
        selectedObject = GameObject.FindGameObjectWithTag("Sphere0");
    } 

我无法定义此类之外的方法。不编译,不确定原因

3 个答案:

答案 0 :(得分: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>
 {
   // ...
 };

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

答案 1 :(得分:0)

您还可以使用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模板参数。

答案 2 :(得分: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;
}