如何创建一个函数来转换类< T>到类< U&gt ;,其中T和U是任意数字类型? [英] How to create a function that converts a Class<T> into Class<U>, where T and U are arbitrary number types?

查看:181
本文介绍了如何创建一个函数来转换类< T>到类< U&gt ;,其中T和U是任意数字类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用SFML,我想做如下事情:

  sf :: Texture myTexture; 
myTexture.loadFromFile(texture.png);

sf :: Sprite mySprite(myTexture);
mySprite.setOrigin(myTexture.getSize()/ 2.f); //<〜 - error

问题是 sf :: Texture :: getSize()返回 sf :: Vector2 < unsigned c c> ,而 sf :: Transformable :: setOrigin()需要 sf :: Vector2 < float >



我想创建一个函数接受任何 sf :: Vector2< T> / code>并返回等效的 sf :: Vector< U> ,其中 T U 都是任意数字类型,因此我可以将最后一行代码重写为:

  // from'unsigned'to'float'
mySprite.setOrigin(toVector2< unsigned,float>(myTexture.getSize())/ 2.f);

我到目前为止是以下内容,但不起作用。

  // Util.h 
namespace smi
{
template< typename FROM,typename TO>
sf :: Vector2< TO> toVector2(const sf :: Vector2< FROM>& other)
{
return sf :: Vector2< TO>(
static_cast< TO>(other.x),
static_cast< TO>(other.y));
}
}

// then ...
mySprite.setOrigin(toVector2< unsigned,float>(myTexture.getSize())/ 2.f) ;
// ^没有函数模板的实例toVector2匹配参数列表

显示错误的图片:



匹配



如何实现这样的泛型转换?

解决方案

这是任意类型。



对于特定情况,你通常可以做一些事情like:

 模板< typename To,typename From> 
Thing< To> convert(const Thing< From>& from)
{
return Thing< To>(/ * from * /的内部值)
}

从源对象中保存的值构造新对象。但是,为了做到这一点,你需要知道类型的API,这样你可以得到值,并调用一个合适的构造函数,例如

  template< typename To,typename From> 
std :: complex< To> convert_complex(const std :: complex< From>& from)
{
return std :: complex< To>(from.real(),from.imag
}

或:

  template< typename To,typename From> 
std :: vector< To> convert_vector(const std :: vector< From>& from)
{
return std :: vector< To>(from.begin(),from.end());
}

或:

  template< typename To,typename From> 
std :: shared_ptr< To> convert_shared_ptr(const std :: shared_ptr< From>& from)
{
return std :: dynamic_pointer_cast< To>(from);
}

但是没有办法完全一样,因为每个类型都有



您的 toVector2 函数看起来像它应该工作,因为它正是这样。正如Pete指出的,错误显示你没有定义你的 toVector2 函数,如你的问题所示:你把参数换成另一个!



注意您可以重新排序模板参数,以便可以使用模板参数扣除来简化转换函数:

  template< To,typename From> 
sf :: Vector2< To> toVector2(const sf :: Vector2< From>& other)
{
return ...
}

现在你可以调用 toVector2< float>(myTexture.getSize()) / code>参数将被推导为 unsigned



由于这似乎是你如何定义真正的函数,只需更改代码 toVector2< float>(myTexture.getSize()),它应该工作。


I'm working with SFML, and I'd like to do things like the following:

sf::Texture myTexture;
myTexture.loadFromFile("texture.png");

sf::Sprite mySprite(myTexture);
mySprite.setOrigin(myTexture.getSize() / 2.f); // <~-- error

The problem is that sf::Texture::getSize() returns a sf::Vector2<unsigned>, whilst sf::Transformable::setOrigin() expects for a sf::Vector2<float>, and they're not convertible into each other.

I thought on creating a function that would accept any sf::Vector2<T> and return an equivalent sf::Vector<U>, where T and U are both arbitrary number types, so I could rewrite that last line of code as:

// converting from 'unsigned' to 'float'
mySprite.setOrigin(toVector2<unsigned, float>(myTexture.getSize()) / 2.f);

What I have so far is the following, but it doesn't work.

// Util.h
namespace smi
{
    template <typename FROM, typename TO>
    sf::Vector2<TO> toVector2(const sf::Vector2<FROM> &other)
    {
        return sf::Vector2<TO>(
            static_cast<TO>(other.x),
            static_cast<TO>(other.y));
    }
}

// then ...
mySprite.setOrigin(toVector2<unsigned, float>(myTexture.getSize()) / 2.f);
// ^ no instance of function template "toVector2" matches the argument list

Here's an image showing the error:

How could I achieve such a generic conversion?

解决方案

In general, you can't do this for arbitrary types. There is not necessarily any relationship between two different specializations of a class template, and no generic way to convert from one to the other.

For specific cases you can usually do something like:

template <typename To, typename From>
  Thing<To> convert(const Thing<From>& from)
  {
    return Thing<To>( /* internal value(s) of from */ );
  }

i.e. construct a new object from the value(s) held in the source object. But to do that you need to know the API of the type, so that you can get the values out and call an appropriate constructor e.g.

template <typename To, typename From>
  std::complex<To> convert_complex(const std::complex<From>& from)
  {
    return std::complex<To>( from.real(), from.imag() );
  }

or:

template <typename To, typename From>
  std::vector<To> convert_vector(const std::vector<From>& from)
  {
    return std::vector<To>( from.begin(), from.end() );
  }

or:

template <typename To, typename From>
  std::shared_ptr<To> convert_shared_ptr(const std::shared_ptr<From>& from)
  {
    return std::dynamic_pointer_cast<To>(from);
  }

But there is no way to do that completely generically, as every type has a different API for getting to its internal values (if it's even possible) and for constructing a new object.

Your toVector2 function looks like it should work though, as it does exactly this. As Pete pointed out, the error shows you have not defined your toVector2 function as shown in your question: you put the arguments the other way around!

N.B. you can re-order the template parameters so that you can use template argument deduction to simplify your conversion function:

template <typename To, typename From>
  sf::Vector2<To> toVector2(const sf::Vector2<From>& other)
  {
    return ...
  }

Now you can just call toVector2<float>(myTexture.getSize()) and the From argument will be deduced as unsigned.

Since that seems to be how you defined the real function anyway, just change the code to toVector2<float>(myTexture.getSize()) and it should work.

这篇关于如何创建一个函数来转换类&lt; T&gt;到类&lt; U&gt ;,其中T和U是任意数字类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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