【问题标题】:Undefined operator error when using specialised template使用专用模板时出现未定义的运算符错误
【发布时间】:2016-10-20 08:15:56
【问题描述】:

我在 Visual Studio 2015 社区版中使用最新版本的 MSVC,但在模板专业化和运算符重载方面遇到了一些问题。

我有以下(仅标题)矢量类 sn-p。我已经排除了不必要的代码(即 vec2 和 vec4 的相同特化)。

template <typename T, int n>
struct VectorN
{
    T data[n];

    T& operator[](const int i);
};

template <typename T, int n>
T& VectorN<T, n>::operator[](const int i)
{
    static_assert(i >= 0 && i < n, "Index out of range");
    return data[i];
}

template <typename T, int n>
std::ostream& operator<<(std::ostream& os, const VectorN<T, n>& vec)
{
    for (auto i = 0; i < n; ++i)
    {
        os << vec[i];
    }
    return os;
}

具有以下专业:

template <typename T>
struct VectorN<T, 3>
{
    union
    {
        T data[3];

        struct
        {
            T x, y, z;
        };
    };
};

typedef VectorN<int, 3> Vec3i;
typedef VectorN<float, 3> Vec3f;

我正在编译的主要功能是:

int main(int argc, char *argv[])
{
    Vec3f vec{ 0, 1, 2 };

    std::cout << vec << std::endl;

    char dump;
    std::cin >> dump;
    std::cin.clear();

    return 0;
}   

我希望它可以工作,但是,我收到了 Error: C2676 binary '[': 'const VectorN&lt;float,3&gt;' does not define this operator or a conversion to a type acceptable to the predefined operator

我相信 ostream 运算符按预期工作,但索引运算符不是。有什么我正在做的事情显然是错误的,还是当前的 MSVC 根本不支持我正在尝试做的事情?

【问题讨论】:

  • 专业化无权访问其基本模板的成员。你可以创建一个通用的基类来继承。

标签: c++ c++11 visual-c++ c++14


【解决方案1】:

如果您想保留基于union 的解决方案来访问具有dataxyz 的3 维向量,您可以使用CTRP 创建一个基知道派生类的data 成员的类:

namespace impl
{
    template <typename T, int n, typename TDerived>
    struct VectorBase
    {
        const T& operator[](const int i) const
        {   
            assert(i >= 0 && i < n);
            return static_cast<const TDerived&>(*this).data[i];
        }
    };
}

您的派生类可以按如下方式实现:

template <typename T, int n>
struct VectorN : impl::VectorBase<T, n, VectorN<T, n>>
{
    T data[n];
};

template <typename T>
struct VectorN<T, 3> : impl::VectorBase<T, 3, VectorN<T, 3>>
{
    union
    {
        T data[3];

        struct
        {
            T x, y, z;
        };
    };

    VectorN(T ax, T ay, T az) : data{ax, ay, az} {}
};

working example is available on wandbox

【讨论】:

  • 谢谢!这看起来棒极了。看起来也没有运行时间成本?当我有时间来测试这个时,我会给你打勾。
  • 太好了,完美运行!感谢您解释一个仍然保持我想做的解决方案:)
  • 啊@Vittorio-Romeo,但是,这缺少我无法弄清楚的一件事。如何启用非常量引用返回?我希望该值是可修改的,但如果我这样做,我会再次遇到问题。首先,删除 const 抱怨 cannot convert from 'const float' to 'float &amp;',其次,如果我从 static_cast 中删除 const,我会遇到与原始帖子相同的问题...
  • 为长链道歉,但我通过简单地使用 const 和非 const 版本的运算符解决了这个新问题。万一将来有人看到这个并且想知道;)
【解决方案2】:

operator&lt;&lt; 有效,因为您的 VectorN 模板类型有适当的重载。

另一方面,operator[] 不起作用,因为在VectorN 的专用版本中没有operator[](编译器请告诉您)。

您可以将operator[] 添加到VectorN 类的专用版本,或者如@DeiDei 所述,尝试将一些功能移至基类。

【讨论】:

    猜你喜欢
    • 2020-12-11
    • 2015-05-01
    • 2015-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-26
    相关资源
    最近更新 更多