简体   繁体   English

仅在模板类的特定特化上声明成员函数

[英]Declare member function only on specific specialization of templated class

I have a templated class to aid in compile time computation of physical quantities.我有一个模板类来帮助物理量的编译时计算。 It uses the extra template parameters ( std::ratio ) to ensure things like a Length can only be added to a Length , or that Area is a Length times a Length .它使用额外的模板参数( std::ratio )来确保只能将Length之类的内容添加到Length中,或者AreaLength乘以Length

#include <ratio>

template <
  typename Length      = std::ratio<0>, // Meter
  typename Mass        = std::ratio<0>, // Kilogram
  typename Time        = std::ratio<0>, // Second
  typename Current     = std::ratio<0>, // Ampere
  typename Temperature = std::ratio<0>, // Kelvin
  typename Amount      = std::ratio<0>, // Mole
  typename Luminous    = std::ratio<0>  // Candela
>
class Quantity {
private:
  double value;
public:
  constexpr Quantity(double val) : value(val) {}

  Quantity &operator+=(Quantity const &that) {
    value += that.value;
    return *this;
  }

  // ...
};

But sometimes I want to convert back to a simple double , for interfacing with other stuff.但有时我想转换回一个简单的double ,以便与其他东西交互。

I could add a member function for the templated class that returns the internal double - or enables implicit (or explicit) conversion to double when a double is needed.我可以为返回内部double精度的模板类添加一个成员函数 - 或者在需要double精度时启用隐式(或显式)转换为double精度。

  constexpr double getValue() { return value; }
  constexpr operator double() { return value; }

However, I really only want this implicit conversion to happen when the "dimensions" of the quantity are all 0 (all template parameters are 0).但是,我真的只希望在数量的“维度”全部为 0(所有模板参数为 0)时发生这种隐式转换。

I could just declare the same member functions and only define the specialization that I want.我可以只声明相同的成员函数,只定义我想要的特化。 But that still declares that the conversion exists for types that I don't ever want to allow conversion from (you should divide by your desired units first).但这仍然声明对于我不想允许转换的类型存在转换(您应该首先除以所需的单位)。 This makes my editor tell me it's ok but it won't link at compiletime.这让我的编辑告诉我没关系,但它不会在编译时链接。

Is there a way to declare member functions only on certain specializations?有没有办法只在某些特化上声明成员函数?

Of note, I'm stuck on C++14 for now, otherwise I think an if constexpr could work...值得注意的是,我现在坚持使用 C++14,否则我认为if constexpr可以工作......

No, if constexpr cannot be used to provide for conditional definition of class methods.不, if constexpr不能用于提供类方法的条件定义。 if constexpr belongs in some method or a function, so that needs to be declared before anything can be done with if constexpr , and your goal is to not even declare it in the first place. if constexpr属于某个方法或函数,因此需要先声明它,然后才能使用if constexpr完成任何操作,而您的目标甚至是一开始就不要声明它。

There is no way to directly instantiate a class method only for certain specializations or template instances, however there's a common approach that comes pretty close: simulate an overload resolution failure.没有办法只为某些特化或模板实例直接实例化类方法,但是有一种非常接近的通用方法:模拟重载解析失败。

Here's a simplified example:这是一个简化的示例:

#include <type_traits>
#include <iostream>

template<typename T>
struct life {
    template<typename=
         typename std::enable_if<std::is_same<T,int>::value>::type>
    constexpr int answer()
    {
        return 42;
    }
};

int main()
{
    life<int> of_brian;

    std::cout << of_brian.answer() << std::endl; // Shows 42

    life<double> of_black_night;

    std::cout << of_black_night.answer() << std::endl; // Error
    return 0;
}

The template class effectively implements answer() only for its int instance.模板类仅对其int实例有效地实现answer() gcc 's error message, for attempting to invoke it from an undesirable instance of the template is: gcc的错误消息,用于尝试从不需要的模板实例调用它是:

error: no matching function for call to 'life<double>::answer()'错误:没有匹配函数调用 'life<double>::answer()'

which is a pretty close facsimile for "this doesn't exist, pal".这是“这不存在,伙计”的非常接近的传真。

This is logically equivalent to what you're attempting to do with your template, the only difference is that you need to check a bunch of template parameters, instead of just one.这在逻辑上等同于您尝试对模板执行的操作,唯一的区别是您需要检查一堆模板参数,而不仅仅是一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM