在模板实例化中包括和排除类型

时间:2019-05-24 08:55:09

标签: c++ templates specialization

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

专业化将产生代码膨胀,其中包含永远不会使用的代码。 (我只能生成抛出异常的ctor)。

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

理想情况下,应该有一个编译器消息,上面写着“不允许...实例化。”

允许模板的明确列表太严格了。

3 个答案:

答案 0 :(得分:3)

您可以使用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.");

答案 1 :(得分:2)

如果要防止为特定类型实例化,则可以仅将模板的特定专业定义为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

答案 2 :(得分:1)

出于完整性考虑,还有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。将支票放入功能模板的签名中是实现此目的的唯一方法。

相关问题