包括并从模板实例化中排除类型

Including and excluding types from template instantiation

本文关键字:排除 类型 实例化 包括      更新时间:2023-10-16

我想从模板实例化中抑制某些类型。我想在库中实现一种仅适用于实数,而不适用于复杂或整数类型的算法。因此,使用float/double/long double/mpf_class的用户实例应该可以,但即 complex<float> 必须不发生。

专业会产生代码膨胀,而代码将永远不会使用。(我只能生成CTOR,只会投掷异常(。

template<typename T>
void work (T & result, T const & input) { /* work for any real type */ }

理想情况下,应该有一个编译器消息,上面写着"不允许这样的实例化"。

允许模板的明确列表太限制了。

您可以使用static_assert生成所需的确切编译时错误消息:

#include <type_traits>
template<typename T>
void work (T & result, T const & input)
{
    static_assert(std::is_floating_point<T>::value, "Only floating point types are allowed.");
    // ...
}

如果您使用的是C 17,则可以短一点:

static_assert(std::is_floating_point_v<T>, "Only floating point types are allowed.");

,如果要防止特定类型的实例化,则可以将模板的特定专业定义为delete D。

一个最小的示例,以防止用T=int实例化:

template<typename T>
void work (T & result, T const & input) { (void)result; (void)input; }

template<>
void work (int & result, int const & input) = delete;
int main()
{
    float f1 = 3.14;
    float f2 = 1.414;
    work(f1, f2); //works
    int i1 = 1;
    int i2 = 2;
    work(i1, i2); //Doesn't work
}

编译器将投诉使用int进行实例化。

error: use of deleted function 'void work(T&, const T&) [with T = int]'
   16 |     work(i1, i2); //Doesn't work

demo

出于完整的清晰度,还有sfinae。

template<typename T>
auto work (T & result, T const & input) -> std::enable_if_t<std::is_floating_point_v<T>>
{
  // ..
}

省略了void,因为它是默认类型enable_if_t在条件下的情况下解决。这只是一种风格的选择。

这里的区别在于,该函数甚至不被认为存在于过载分辨率中。因此,您可以在其他SFINAE上下文中检查work是否可以使用参数。将检查放入函数模板的签名是实现此目的的唯一方法。