-2

假设我想定义一组函数,每个函数有 4 个重载,第一个重载采用单个类型参数,int32_t第二个采用int64_t,第三个 -uint32_t和第四个 - uint64_t。对于每个函数,所有重载都有相同的实现,所以我可以定义一个函数模板:

template <typename T>
void f(T t) {
  // ...
}

然而,这与有四个重载不同,因为现在我为每个(整数)类型都有一个单独的函数,可用于实例化f. 但是,它的实现细节f可能不适用于其他整数类型。为了解决这个问题,我可以将函数模板包装在四个重载函数中:

template <typename T>
void f_impl(T t) {
  // ...
}

void f(int32_t value) { f_impl(value); }
void f(int64_t value) { f_impl(value); }
void f(uint32_t value) { f_impl(value); }
void f(uint64_t value) { f_impl(value); }

它可以工作,但每个函数都需要大量代码(4 个函数重载 + 1 个函数模板)。有没有办法简化这个?

澄清一下,直接使用模板是不可取的,因为(出于实现原因或其他原因)对int32_t,int64_t和.uint32_tuint64_t


我已经尝试过使用std::enable_if,这个例子最好地说明了它的问题:

#include <type_traits>
#include <iostream>

template <typename T>
struct is_supported_int {
  static const bool value = false;
};

template <>
struct is_supported_int<int32_t> {
  static const bool value = true;
};

template <>
struct is_supported_int<int64_t> {
  static const bool value = true;
};

// ...

template <typename T, typename = typename std::enable_if<is_supported_int<T>::value, T>::type>
void f(T t) {
// ...
}

int main() {
  short s = 42;
  f(s);
}

与我试图模拟的具有重载的原始版本不同,此示例将无法编译,因为f它将被排除在short.

不幸的是std::is_integral<T>,正如 Rapptz 所建议的那样,这也无济于事,因为由于f此函数的实现细节只能为特定类型定义,而不是为所有整数类型定义。

4

2 回答 2

5

像这样的东西会起作用。

#include <type_traits>
#include <iostream>

template<typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type>
void f(T t) {
    std::cout << "int types only!\n";
}

int main() {
    f(1.234f);
    f(12);
}

f(1.234f) 将无法编译,但 f(12) 不会。

于 2013-01-13T18:31:01.053 回答
0

使用enable_if或静态断言来限制实例化。

#include <type_traits>
#include <cstdint>

template<bool X, bool Y>
struct or_ : std::true_type 
{};

template<>
struct or_<false, false> : std::false_type 
{};

template<typename T>
struct valid_type_for_f :
  or_< std::is_same<T, std::uint32_t>::value,
       std::is_same<T, std::uint64_t>::value> // etc.
{};

// static assert
template<typename T>
T f(T t) {
  static_assert(valid_type_for_f<T>::value, "Not a valid type");
  return t;
}

// enable_if
template<typename T>
typename std::enable_if<valid_type_for_f<T>::value, T>::type
fenable(T t) {
  return t;
}


int main()
{
  float x = 4.2f;
  f(x); // fails
  fenable(x); // fails
  std::uint32_t xx = 23;
  f(xx);
  fenable(xx);
  return 0;
}
于 2013-01-13T18:42:20.720 回答