1
저는 수학적 벡터 클래스를 만들고 있습니다.벡터 연산자와 형식 변환
그 운영 전환이 C에서 POD 유형과 작동하는 방식과 유사한 종류의 사이에/경고 동작을 변환을 제공하기 위해 내가 좋아하는 것은 ++, 예를 들면 : 나는 그것을 알고있는 것처럼
//{
// auto f = 1.f;
// auto d = 2.0;
// f *= d; // warns about possible loss of data
// d *= f; // fine
// auto d2 = f * d; // fine (f promotion, d2 is double)
//}
, 나는 표준을 사용해야합니다 : common_type을 사용하여 올바른 유형을 찾으십시오. 불행하게도, 내가 얻을 같은 컴파일러 오류 : 그래서
template<class ElementT, unsigned int Dimensions>
class Vector
{
public:
typedef ElementT ElementT;
static const unsigned int Dimensions = Dimensions;
typedef std::array<ElementT, Dimensions> DataT;
Vector():
data() { }
explicit Vector(std::initializer_list<ElementT> values):
data()
{
std::copy(values.begin(), values.end(), data.begin());
}
template<class E>
explicit Vector(Vector<E, Dimensions> const& other):
data()
{
std::copy(other.Data().begin(), other.Data().end(), data.begin());
}
Vector& operator*=(ElementT value)
{
for (auto& e : data)
e *= value;
return *this;
}
Vector& operator*=(Vector const& other)
{
for (auto i = 0u; i != data.size(); ++i)
data[i] *= other.data[i];
return *this;
}
// etc. ...
// Warnings are still propagated from the copy constructor
// if this is used with inappropriate types...
template<class E>
operator Vector<E, Dimensions>() const
{
return Vector<E, Dimensions>(*this);
}
DataT& Data()
{
return data;
}
DataT const& Data() const
{
return data;
}
private:
friend std::ostream& operator<<(std::ostream& stream, Vector v)
{
for (auto const& e : v.data)
stream << e << " ";
return stream;
}
DataT data;
};
template<class E, unsigned int D>
Vector<E, D> operator*(Vector<E, D> const& v, E value)
{
auto result = Vector<E, D>(v);
result *= value;
return result;
}
template<class E, unsigned int D>
Vector<E, D> operator*(Vector<E, D> const& v1, Vector<E, D> const& v2)
{
auto result = Vector<E, D>(v1);
result *= v2;
return result;
}
template<class E, class T, unsigned int D>
Vector<std::common_type_t<E, T>, D> operator*(Vector<E, D> const& v, T value)
{
auto result = Vector<std::common_type_t<E, T>, D>(v);
result *= value;
return result;
}
template<class E1, class E2, unsigned int D>
Vector<std::common_type_t<E1, E2>, D> operator*(Vector<E1, D> const& v1, Vector<E2, D> const& v2)
{
auto result = Vector<std::common_type_t<E1, E2>, D>(v1);
result *= v2;
return result;
}
void TestVector()
{
std::cout << "Testing Vector" << std::endl;
using Vec3 = Vector<float, 3u>;
// Same types. All fine.
{
auto v1 = Vec3({ 1, 2, 3 });
auto v2 = Vec3({ 1, 2, 3 });
v1 *= 2.f;
v1 *= v2;
std::cout << v1 << std::endl;
}
{
auto v1 = Vec3({ 1, 2, 3 });
auto v2 = Vec3({ 1, 2, 3 });
std::cout << (v1 * 2.f) << std::endl;
std::cout << (v1 * v2) << std::endl; // causes problems with std::common_type?
}
{
auto v1 = Vector<float, 3u>({ 1, 2, 3 });
auto v2 = Vector<double, 3u>({ 1, 2, 3 });
v1 *= 2.0; // should probably produce a warning, but doesn't? :(
v1 *= v2; // compiles with warning :)
v2 *= v1; // fine :)
std::cout << v1 << std::endl;
}
{
// The std::common_type versions seem to conflict?
auto v1 = Vector<float, 3u>({ 1, 2, 3 });
auto v2 = v1 * 2.0; // v1 promotion -> should create a Vector<double, 3u>
auto v3 = v1 * v2; // v1 promotion -> should create another Vector<double, 3u>
std::cout << v2 << std::endl;
}
}
:
- 내가 정상적인 필요를 모두 수행하고, 표준 : common_type 연산자 버전 여기
는 관련 코드 ?1>C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\type_traits(1446): error C2446: ':' : no conversion from 'Testing::Vector<float,3>' to 'float' 1> No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called 1> TestVector.cpp(152) : see reference to class template instantiation 'std::common_type<float,Testing::Vector<float,3>>' being compiled
- std :: common_type을 사용하는 벡터 및 스칼라 버전이 간섭하는 것 같습니다. 이것을 막을 수 있습니까?
- 어떻게하면됩니까?
감사합니다.
영감을주는 예제 추가 (** [live on coliru] (http://coliru.stacked-crooked.com/a/d4da3cc344ac86d9) **) – sehe
감사합니다. 템플릿 매개 변수 목록에 std :: common_type이있는 것으로 보입니다. 여기에 내가 결국에 들어갔습니다 : http://coliru.stacked-crooked.com/a/b96c12724a2dc3fc – user673679
@ user673679 예, 가능하다고 생각됩니다. 인수 목록이나 반환 형식에 넣으면 ** [SFINAE] (http://en.cppreference.com/w/cpp/language/sfinae) **가 가능합니다. 여기서 컴파일러는 대체가 발생할 수있는 오버로드를 자동으로 무시할 수 있습니다. 오류 _ 선언에 _. 귀하의 경우에는 다른 '연산자 *'오버로드가있는 경우 쉽게 발생할 수 있으며, 호출하면 SFINAE 때문에 스칼라 버전이 삭제됩니다. – sehe