【发布时间】:2015-10-15 08:25:20
【问题描述】:
我目前正在研究一个小型数学向量类。
我想要两个向量类,Vector2 和 Vector3 可以从一个到另一个构造。
例如:
Vector2<float> vec2(18.5f, 32.1f); // x = 18.5; y = 32.1
Vector3<float> vec3(vec2); // x = 18.5; y = 32.1; z = float()
为此,为了简化可扩展性,我想使用带有基本定义的特征VectorTraits:
template <typename T>
struct VectorTraits
{
typedef T VectorType;
typedef typename T::ValueType ValueType;
static const unsigned int dimension = T::dimension;
};
此表单将允许用户在现有的 Vectors 类(例如 glm::vec2)和我的类之间建立链接。然后可以从 glm::vec2 创建 Vector2。
此外,这种技术可以让我为所有使用 SFINAE 定义 VectorTraits 的类编写通用流式操作符。
我的问题是,我无法定义operator<<,所以当VectorTraits 不适合给定类型时,这是一个静默错误。
这是我最后一次尝试 (Ideone link here):
#include <iostream>
#include <type_traits>
// To define another operator
struct Dummy
{};
// Traits class
template <typename T>
struct VectorTraits
{
typedef T VectorType;
typedef typename T::ValueType ValueType;
static const std::uint16_t dimension = T::dimension;
};
// Fake vector class. Defines the required typedef.
struct Vec
{
typedef float ValueType;
static const std::uint16_t dimension = 2;
};
// Streaming operator for Dummy.
std::ostream& operator<<(std::ostream& stream, const Dummy& d)
{
stream << "dummy.\n";
return stream;
}
// Streaming operator attempt for classes defining VectorTraits.
template <class T, std::enable_if_t<(VectorTraits<T>::dimension > 0)>>
std::ostream& operator<<(std::ostream& stream, const T& vec)
{
std::cout << "Traits. Dimension = " << VectorTraits<T>::dimension << "\n";
}
int main()
{
std::cout << "Test\n";
std::cout << Vec();
std::cout << Dummy();
return 0;
}
通过这种尝试,错误只是
error: no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'Vec')
prog.cpp:33:15: note: candidate: template<class T, typename std::enable_if<(VectorTraits<T>::dimension > 0), void>::type <anonymous> > std::ostream& operator<<(std::ostream&, const T&)
std::ostream& operator<<(std::ostream& stream, const T& vec)
^
prog.cpp:33:15: note: template argument deduction/substitution failed:
prog.cpp:41:19: note: couldn't deduce template parameter '<anonymous>'
如果我改变了
template <class T, std::enable_if_t<(VectorTraits<T>::dimension > 0)>>
到
template <class T, std::enable_if_t<(VectorTraits<T>::dimension > 0)>* = 0>
我得到另一个错误
prog.cpp:13:35: error: 'char [21]' is not a class, struct, or union type
typedef typename T::ValueType ValueType;
我设法开始工作的唯一版本是一个空的VectorTraits 类,它必须专门用于每个Vector。但我也想提供一种“自动”成为 Vector 并定义了一些 typedefs 的方法。
我不明白为什么在显示版本中,我的运算符没有被编译器保留。我也尝试了一些变体,但它总是要么匹配所有内容,要么什么都不匹配。
【问题讨论】:
-
您是否想要一个只选择 your 向量的特征(在这种情况下,您有一个空的主模板并专门针对您的向量),或者您是否需要想要检测 any 类向量类型。在后一种情况下,您需要一个通用的存在检查特征来检查一个类型是否具有某种类型的成员等。
-
就我而言,我真的希望能够厌恶任何类似
Vector的类型。但我一直无法理解如何正确实现这一目标。不仅仅是解决方案,我真的很想了解我在这里缺少什么。 -
如果您指定该实现的实际问题(发布实际错误消息或您得到的任何内容),这将有所帮助。正如现在写的那样,它只是“不起作用”。
-
(有点切题,pretty printer code 包含一个检测“任何看起来像容器的东西”的特征。也许这让您对用于此类选择机制的那种 TMP 有所感觉。)跨度>
-
@Petr 我忘了这样做。我已经用更多信息更新了这个问题。
标签: c++ templates c++11 sfinae