C ++如何从1个模板类转换为另一个?

时间:2015-08-23 18:15:42

标签: c++ templates casting

我有一个我打算使用的类,类型为floatdouble。据我所知,没有办法限制模板选项,所以也许我可能会在这里做一些危险的事情?

template<class T>
class A
{
    A(T arg) { _data = arg; }

    T _data;
}

typedef A<float> A_f;
typedef A<double> A_d;

我该怎样做?

int main()
{
    A_f f(3.1415);
    A_d d(3.1415);
    f = (A_f)d;
}

IE:将包含double类型数据的类转换为包含float类型数据的类。

编辑:这似乎无处可去,所以我试着玩弄这个,但显然我不知道该怎么办,所以它不会编译...

template<class T>
class A
{
    friend                    // Intention is for T to be double here
    A<float> operator A<float>(const A<T> input);
}

A<float> operator A<float>(const A<double> input)
{
    return A<float>(input._data);
}

也许这有助于解释我想要实现的目标?

亚当的第二次编辑:

return A<float>((float)input._data);

这样更好吗?

5 个答案:

答案 0 :(得分:2)

您可以使用std::enable_if仅允许某些类型:

#include <type_traits>
using namespace std;

// Our catch-all is not defined, so will not compile
// Could also be made to print a nice error message
template<typename T, typename Sfinae = void> class A;

// Ok if T is float or double
template<typename T>
class A<T, typename std::enable_if<std::is_same<T, float>::value
                                || std::is_same<T, double>::value>::type>
{
    // Your class here
};

int main()
{
    A<int> a; // FAILS
    A<float> b; // Ok
    A<double> c; // Ok

    return 0;
}

然后,您只需在类中定义转换运算符,即可使转换工作。

答案 1 :(得分:1)

不要强制转换,而是提供一个(且只有一个)隐式转换构造函数或转换运算符。在您的情况下,它可能与operator T () const { return _data; }

一样简单

答案 2 :(得分:1)

我会说你不应该这样做的论点,但如果你坚持,添加一个模板化的复制构造函数:

template<class T>
class A
{
public:                                 // add this
    A(T arg) { _data = arg; }

    template <class U>                  // add this
    A(A<U> arg) { _data = arg._data; }  // add this

    T _data;
}

只要A<U>可以隐式转换为A<T>,就会允许从U转换为T

答案 3 :(得分:0)

可以根据您提供的类型自定义类。该技术被称为模板专业化&#39;

#include <iostream>
using namespace std;

template <typename T>
class A {
public:
    void print_my_type() { 
        cout << "Generic template instance" << endl; 
    }

    explicit operator A<int>() const {
        cout << "Casting to int" << endl;
        return A<int>();
    }
};

template <>
class A<int> {
public:
    void print_my_type() { 
        cout << "Class templated with an int" << endl; 
    }

    explicit operator A<double>() const {
        cout << "Casting to double" << endl;
        return A<double>();
    }
};

int main() {
    A<double> a;
    A<int> b;

    a.print_my_type();
    b.print_my_type();

    a = static_cast<A<double>>(b);

    return 0;
}

你不应该像那样投射物体。如果您打算将一个对象转换为另一个对象。您应该提供operator A()方法,以便它可以优雅地处理转换

答案 4 :(得分:0)

模板转换运算符示例+ static_assert用于类型验证:

http://coliru.stacked-crooked.com/a/6b01010ea5f02aee

#include <vector>
#include <iostream>

template < typename T > class TD; // type visualiser

template<class T>
class A
{
    public:
    A(T arg) { _data = arg; }

    template<typename D>
    operator A<D>() {
      static_assert(std::is_same<D, float>::value || std::is_same<D, double>::value, "double/floats allowed only");
      //TD<D>();  // D is float here
      return static_cast<D>(_data);
    }

    T _data;
};

typedef A<float> A_f;
typedef A<double> A_d;
typedef A<int> A_i;

int main() {
   A_f f(3.14151);
    A_d d(3.14152);

    std::cout << f._data << std::endl;
    std::cout << d._data << std::endl;    

    f = (A_f)d;
    //f = (A_i)d; // static assertion here

    std::cout << f._data << std::endl;
    return 0;
}

[编辑]

template<class T>
class A
{
public:
   A(T arg) { _data = arg; }

  template<typename D>
  operator A<D>() {
    static_assert(std::is_same<D, float>::value || std::is_same<D, double>::value, "double/floats allowed only");
    //TD<D>();  // D is float here
    return A<D>(static_cast<D>(_data));
  }

  T _data;
};