使用概念选择类模板特化 [英] Using concepts to select class template specialization

查看:28
本文介绍了使用概念选择类模板特化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题 演示了如何使用 C++20 概念为 函数 模板选择重载.我正在尝试做一些类似的事情:为 class 模板选择 specializations.

This question demonstrates how to use C++20 concepts to choose overloads for a function template. I'm trying to do something analogous: choose specializations for a class template.

我从 Angle 的类模板开始,它包装了一个包含以弧度表示的角度的浮点值.使用概念,我可以确保用户不会使用浮点类型以外的任何东西实例化 Angle:

I'm starting with a class template for Angle<T> which wraps a floating point value containing an angle in radians. Using concepts, I can ensure that users don't instantiate Angle with anything other than a floating point type:

template <std::floating_point T> struct Angle { T m_radians; };

后来,我决定让客户使用可以处理整数类型的 Angle 的独特实现.换句话说,我想允许这样的代码:

Later, I decided I'd like to let clients use a distinct implementation of Angle<T> that can handle integral types. In other words, I'd like to allow code like:

const auto theta = Angle<float>(3.14f);
const auto phi = Angle<int>(180);

所以我尝试添加一个类似的模板.

So I tried adding a comparable template.

template <std::integral T> struct Angle { T m_degrees; };

编译器将此附加实现视为具有不同约束的模板的重新声明.我尝试了几种不同的方式来表达我的意图,但没有一种方法能满足我尝试过的任何编译器.事实上,我什至找不到用 std::enable_if 和传统 SFINAE 来做到这一点的方法——不可否认,我完全有可能不太了解 SFINAE.

The compilers view this additional implementation as a redeclaration of the template with a different constraint. I've tried several different ways of expressing my intent, but none satisfy any of the compilers I've tried. In fact, I cannot even find a way to do this with std::enable_if and traditional SFINAE--admittedly, it's entirely possible I don't understand SFINAE very well.

我发现的唯一方法是对每个整数和浮点类型进行不同的专门化.

The only approach I've found requires making distinct specializations for each of the integral and floating point types.

template <std::floating_point T> struct AngleRad { T m_radians; };
template <std::integral T> struct AngleDeg { T m_degrees; };

template <typename T> struct Angle2 {};
template <> struct Angle2<float> : public AngleRad<float> {};
template <> struct Angle2<double> : public AngleRad<double> {};
template <> struct Angle2<long double> : public AngleRad<long double> {};
template <> struct Angle2<short> : public AngleDeg<short> {};
template <> struct Angle2<int> : public AngleDeg<int> {};
template <> struct Angle2<long> : public AngleDeg<long> {};
template <> struct Angle2<long long> : public AngleDeg<long long> {};
template <> struct Angle2<unsigned short> : public AngleDeg<unsigned short> {};
template <> struct Angle2<unsigned int> : public AngleDeg<unsigned int> {};
template <> struct Angle2<unsigned long> : public AngleDeg<unsigned long> {};
template <> struct Angle2<unsigned long long> : public AngleDeg<unsigned long long> {};

[是的,我知道还有一些整数类型.我只是想说明这一点.这个例子是为了简单而设计的,尽管它的灵感来自于实际代码.]

[Yes, I know there are a few more integral types. I'm just trying to illustrate the point. This example is contrived for simplicity, though it's inspired by actual code.]

有没有办法用概念来更简单地表达这一点?

Is there a way to use concepts to express this more simply?

推荐答案

你说

template<typename T> // requires (std::integral<T> || std::floating_point<T>) // optional
struct Angle;
template<std::integral T> struct Angle<T> { T m_degrees; };
template<std::floating_point T> struct Angle<T> { T m_radians; };

需要使用足够大的域来声明模板以包含其所有特化.

The template needs to be declared with a big enough domain to contain all of its specializations.

这篇关于使用概念选择类模板特化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆