这是一个可编辑的样本,我从几个头文件中拼凑而成。代码没有意义,因为我扼杀了所有不相关的部分,但要点是我实施了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)上编译良好:
然而,它无法在VS Express 2013上编译:
从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];
它工作正常。有什么想法吗?
答案 0 :(得分:4)
这似乎是更多的MSVC模板破解。它拒绝在此代码中实例化Proxy<double>
,导致重载解析失败。简单地在Proxy<double> p;
的定义之前添加CRIXUS_MA
,强制进行隐式实例化,足以使代码编译。根据§14.7.1[temp.inst] / p6:
如果是,则隐式实例化类模板特化 类类型用于需要完全定义的上下文中 对象类型或类类型的完整性可能会影响 程序的语义。 [注意:特别是,如果语义为 表达式取决于类的成员或基类列表 模板专业化,类模板专业化 隐式生成。例如,删除指向类类型的指针 取决于类是否声明析构函数,和 指向类类型的指针之间的转换取决于继承 涉及的两个阶级之间的关系。 - 结束记录]
由于sum += input[-j];
的语义显然取决于Proxy<double>
的定义,因此它应该被隐式实例化。