You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中如何忽略模板参数判断类型是否属于同一维度

问题:在C++中忽略模板参数判断类型所属维度

在C++中,我需要判断两种类型是否属于同一维度(如mass),以便对同维度类型执行转换,不同维度则禁止操作。现有代码结构如下:

首先是维度基类与具体维度模板:

template<Ratio prefix, Symbol S>
class base_magnitude {}; /* ... 用于表示比率和符号的其他类型 */

template <Ratio R, Symbol S>
class mass: public base_magnitude<R, S> {};

template <Ratio R, Symbol S>
class length: public base_magnitude<R, S> {};

然后是具体的单位类型定义:

struct Kilogram: public mass<Kilo, kg> {
    using dimension = mass;
    using ratio = Kilo;
};
struct Hectogram: public mass<Hecto, hg> {
    using dimension = mass;
    using ratio = Hecto;
};
struct Kilometer: public length<Kilo, km> {
    using dimension = length;
    using ratio = Kilo;
};

我尝试用concept来检查同维度,但遇到问题:

template <typename T>
concept Magnitude = requires {
    typename T::dimension;
    typename T::ratio;
};

template <typename T, typename R>
concept SameMagnitude = requires {
    requires Magnitude<T> && Magnitude<R>;
    requires std::is_same_v<typename T::dimension, typename R::dimension>;
};

实际中,using dimension = mass会被解析为实例化后的具体类型:

  • Kilogram的dimension是mass<Kilo, kg>
  • Hectogram的dimension是mass<Hecto, hg>

因此std::is_same_v无法判定两者属于同一维度。我试过SFINAE和标签分发方案,但标签分发需要额外继承类型,会增加公共API复杂度,希望找到更简洁的实现方式。


解决方案:提取模板的原始类型进行比较

核心思路是编写一个模板元函数,从实例化后的模板类中提取其原始模板类型(即去掉模板参数后的模板本身),然后比较两个类型的原始模板是否一致。

1. 实现模板提取元函数

根据模板参数的类型(类型参数/非类型参数),选择对应的实现:

情况1:模板参数为类型参数

template<typename T>
struct get_template;

// 偏特化:匹配任意带类型参数的模板实例
template<template<typename...> class Template, typename... Args>
struct get_template<Template<Args...>> {
    using type = Template;
};

// 便捷别名
template<typename T>
using get_template_t = typename get_template<T>::type;

情况2:模板参数包含非类型参数(如你的Ratio/Symbol)

C++17及以后支持用auto作为非类型模板参数的占位符,因此可以调整为:

template<typename T>
struct get_template;

// 偏特化:匹配任意带非类型参数的模板实例
template<template<auto...> class Template, auto... Args>
struct get_template<Template<Args...>> {
    using type = Template;
};

template<typename T>
using get_template_t = typename get_template<T>::type;

2. 修改SameMagnitude Concept

使用提取的原始模板类型进行比较:

template <typename T>
concept Magnitude = requires {
    typename T::dimension;
    typename T::ratio;
};

template <typename T, typename R>
concept SameMagnitude = requires {
    requires Magnitude<T> && Magnitude<R>;
    // 比较两个维度的原始模板是否相同
    requires std::is_same_v<get_template_t<typename T::dimension>, get_template_t<typename R::dimension>>;
};

效果验证

  • SameMagnitude<Kilogram, Hectogram>:两者的dimension提取后都是mass模板,判定为同一维度
  • SameMagnitude<Kilogram, Kilometer>:前者提取为mass,后者为length,判定为不同维度

该方案无需修改现有维度类或单位类的定义,不会增加公共API复杂度,完全符合需求。


内容的提问来源于stack exchange,提问作者Alex Vergara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 01:01:10