我正在使用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
>
,而sf::Transformable::setOrigin()
则需要sf::Vector2<
} float
>
,并且他们无法相互转换。
我考虑创建一个接受任何sf::Vector2<T>
并返回等效sf::Vector<U>
的函数,其中T
和U
都是任意数字类型,所以我可以重写最后一行代码为:
// converting 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);
// ^ no instance of function template "toVector2" matches the argument list
这是显示错误的图片:
我怎样才能实现这种通用转换?
答案 0 :(得分:3)
通常,您不能对任意类型执行此操作。类模板的两个不同特化之间不一定有任何关系,也没有从一个模板转换到另一个模板的通用方法。
对于特定情况,您通常可以执行以下操作:
template <typename To, typename From>
Thing<To> convert(const Thing<From>& from)
{
return Thing<To>( /* internal value(s) of 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);
}
但是没有办法完全一般地做到这一点,因为每个类型都有不同的API来获取其内部值(如果它甚至可能)以及构建新对象。
你的toVector2
函数看起来应该可以正常工作,因为它确实如此。正如Pete所指出的那样,错误显示你没有定义你的toVector2
函数,如你的问题中所示:你把参数反过来了!
N.B。您可以重新排序模板参数,以便您可以使用模板参数推导来简化转换功能:
template <typename To, typename From>
sf::Vector2<To> toVector2(const sf::Vector2<From>& other)
{
return ...
}
现在您可以致电toVector2<float>(myTexture.getSize())
,From
参数将推断为unsigned
。
因为这似乎就是你如何定义真实函数的方法,只需将代码更改为toVector2<float>(myTexture.getSize())
它就可以了。
答案 1 :(得分:0)
这是我提出的:
template<typename From, typename To>
std::vector<To> transform_vector(const std::vector<From>& input)
{
std::vector<To> output;
for (const auto& i : input)
output.emplace_back(static_cast<To>(i));
return std::move(output);
}
int main()
{
std::vector<double> test{ 1.5, 3.8, 2 };
std::vector<int> conv = transform_vector<double, int>(test);
for (auto i : conv)
std::cout << i << " ";
std::cout << std::endl;
}
不确定为什么编译器无法推断出类型。