为什么在VS Express 2013中编译这个,虽然它在MinGW中编译?

时间:2014-09-02 05:52:47

标签: c++ compiler-errors visual-studio-2013 mingw visual-studio-express

这是一个可编辑的样本,我从几个头文件中拼凑而成。代码没有意义,因为我扼杀了所有不相关的部分,但要点是我实施了Scott Meyers'数据代理技术(提到here),虽然它演变成更多的包装而不是临时代理。这些都不重要 - 我的问题似乎纯粹是关于编译器行为的差异。

#include <iostream>
#include <vector>

template<typename T>
class Proxy
{
public:
    enum class State
    {
        NEVER_SET = 0,
        SET,
        UNSET
    };
    operator const T& () const
    {
        if ( _state != State::SET )
        {
            std::cout << "EXCEPTION" << std::endl;
            // TODO throw exception
        }
        return _data;
    }
    Proxy<T>& operator=(const T& val)
    {
        _data = val;
        _state = State::SET;
        return (*this);
    }
    Proxy<T>& operator+=(const T& val)
    {
        _data = (*this) + val;
        _state = State::SET;
        return (*this);
    }
private:
    T _data;
    State _state = State::NEVER_SET;
};

class Tape
{
};

template<typename T>
class tape : public Tape
{
public:
    const Proxy<T>& operator[](int idx) const
    {
        return operator[](idx);
    }
    Proxy<T>& operator[](int idx)
    {
        if ( idx >= data.size() )
        {
            data.resize(idx + 1);
        }
        return data[idx];
    }
private:
    std::vector< Proxy<T> > data;
};

class CRIXUS
{
public:
    virtual void Go() final {};
protected:
    virtual void Pre() {};
    virtual void Post() {};
    virtual void Step() = 0;
};

class CRIXUS_MA : public CRIXUS
{
public:
    int window = 30;
    tape<double> input;
    tape<double> output;
protected:
    virtual void Step()
    {
        double sum = 0;
        for ( int j = 0; j < window; j++ )
        {
            sum += input[-j];
        }
        output[0] = sum / window;
    }
};

int main()
{
}

它在Ideone以及Jetbrain的CLion(工具链:MinGW 3.20,CMake 2.8.12.2)上编译良好:

enter image description here

然而,它无法在VS Express 2013上编译:

enter image description here

从CLion运行完整代码(包括读取.csv数字文件并输出移动平均值),我可以验证输出是否正确。只是VS不会编译代码。

据我所知,演员

    operator const T& () const
    {
        if ( _state != State::SET )
        {
            std::cout << "EXCEPTION" << std::endl;
            // TODO throw exception
        }
        return _data;
    }

应将Proxy<T>转换为T即。 Proxy<double>转换为double。当我强行施放违规行时,

        sum += (double)input[-j];

它工作正常。有什么想法吗?

1 个答案:

答案 0 :(得分:4)

这似乎是更多的MSVC模板破解。它拒绝在此代码中实例化Proxy<double>,导致重载解析失败。简单地在Proxy<double> p;的定义之前添加CRIXUS_MA,强制进行隐式实例化,足以使代码编译。根据§14.7.1[temp.inst] / p6:

  

如果是,则隐式实例化类模板特化   类类型用于需要完全定义的上下文中   对象类型或类类型的完整性可能会影响   程序的语义。 [注意:特别是,如果语义为   表达式取决于类的成员或基类列表   模板专业化,类模板专业化   隐式生成。例如,删除指向类类型的指针   取决于类是否声明析构函数,和   指向类类型的指针之间的转换取决于继承   涉及的两个阶级之间的关系。 - 结束记录]

由于sum += input[-j];的语义显然取决于Proxy<double>的定义,因此它应该被隐式实例化。