转换成 Value

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

template <typename T>
Value Value::From(napi_env env, const T& value) {
  using Helper = typename std::conditional<
    std::is_integral<T>::value || std::is_floating_point<T>::value,
    details::vf_number<T>,
    typename std::conditional<
      details::can_make_string<T>::value,
      String,
      details::vf_fallback<T>
    >::type
  >::type;
  return Helper::From(env, value);
}

From 函数将一个 C++ 类型的值转换成 Value 类型。

首先用 using helper 在编译期决定某种类型的 Helper ,然后用 HelperFrom 方法做转换。

std::conditional 的声明如下,如果 Btrue ,它的 type 为 T ,否则为 F。

1
2
template< bool B, class T, class F >
struct conditional;

如果 T 是整数 (std::is_integral) 或者浮点数 (std::is_floating_point) , Helper 就是 details:vf_number ,否者, 如果 T 能够成为 string(details::can_make_string)Helper 就为 String, 否者为 details::vf_fallback

details::vf_number 的代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
template <typename T>
struct vf_number {
  static Number From(napi_env env, T value) {
    return Number::New(env, static_cast<double>(value));
  }
};

template<>
struct vf_number<bool> {
  static Boolean From(napi_env env, bool value) {
    return Boolean::New(env, value);
  }
};

bool 类型的值转换成 Boolean,其他的都转换成 Number

defails:cam_make_string 的代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
template <typename...> struct disjunction : std::false_type {};
template <typename B> struct disjunction<B> : B {};
template <typename B, typename... Bs>
struct disjunction<B, Bs...>
    : std::conditional<bool(B::value), B, disjunction<Bs...>>::type {};

template <typename T>
struct can_make_string
    : disjunction<typename std::is_convertible<T, const char *>::type,
                  typename std::is_convertible<T, const char16_t *>::type,
                  typename std::is_convertible<T, std::string>::type,
                  typename std::is_convertible<T, std::u16string>::type> {};

std::false_type 的原型是 std::integral_constant<bool, false> ,作用是将一个静态常量转换成类型。这里的 std::false_type::valuefalse

std::disjunction 是一个递归的模板,作用是判断 Bs.. 中有一个为 true 整个表 达式的 valuetrue ,否则为 false

所以 can_make_string 判断 T 能不能转换成 char *, char16_t*, string, u16string ,可以 can_make_string::valuetrue, 否则为 false

如果可以转换成 string ,用 StringFrom 方法,否则用 details::vf_fallbackFrom 方法。

StringFrom 方法如下,根据条件判断具体用哪一个类型的 From 方法:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <typename T>
String String::From(napi_env env, const T& value) {
  struct Dummy {};
  using Helper = typename std::conditional<
    std::is_convertible<T, const char*>::value,
    details::vf_utf8_charp,
    typename std::conditional<
      std::is_convertible<T, const char16_t*>::value,
      details::vf_utf16_charp,
      typename std::conditional<
        std::is_convertible<T, std::string>::value,
        details::vf_utf8_string,
        typename std::conditional<
          std::is_convertible<T, std::u16string>::value,
          details::vf_utf16_string,
          Dummy
        >::type
      >::type
    >::type
  >::type;
  return Helper::From(env, value);
}

其中一个类型的 From 方法如下:

1
2
3
4
5
struct vf_utf8_charp {
  static String From(napi_env env, const char* value) {
    return String::New(env, value);
  }
};

vf_fallback 就是构造一个默认的 Value

1
2
3
4
5
6
7
template <typename T>
struct vf_fallback {
  static Value From(napi_env env, const T& value) {
    return Value(env, value);
  }
};