我正在尝试编写一个serialiser。下面的代码编译:为什么这样编译,模板扣除应该失败?
#include <string>
#include <fstream>
#include <type_traits>
#include <map>
#include <iostream>
class SpaceStream
{
public:
SpaceStream(const std::string& filename)
:
m_file(filename)
{
}
template<typename T>
typename std::enable_if<std::is_class<T>::value>::type
Add(const std::string& key, const T& t)
{
m_file << key;
m_file << ":{";
t.Serialise(*this);
m_file << "},";
}
template<typename T>
typename std::enable_if<!std::is_class<T>::value && !std::is_pointer<T>::value && !std::is_reference<T>::value>::type
Add(const std::string& key, const T t)
{
m_file << key;
m_file << ':';
m_file << t;
m_file << ',';
}
private:
std::ofstream m_file;
std::map<std::string,std::string> m_pointerObj;
};
class ISerialise
{
public:
virtual void Serialise(SpaceStream& stream) const = 0;
};
class Test1 : public ISerialise
{
public:
int m_x;
int& m_rx;
Test1(int& x)
:
m_x(x), m_rx(x)
{
}
virtual void Serialise(SpaceStream& stream) const
{
stream.Add("x",m_x);
stream.Add("xr",m_rx);
}
};
int main()
{
int j = 13;
Test1 test(j);
j = 23;
SpaceStream ss("somefile.ss");
ss.Add("testobj",test);
}
我还以为这条线:
stream.Add("xr",m_rx);
会因为两个Add
功能失效,一个专门检查该类型不是一类,另一方检查它不是参考。 m_rx
是一个引用类型,所以它应该失败?
编辑 我现在明白,类型实际上是一个值,而不是一个参考。我需要能够识别引用,以便我可以跟踪它们(我只想将数据序列化一次,并引用它)。
指定的模板参数“*我需要能够识别引用,这样我可以跟踪他们*“你是什么意思? –
这与真空没有什么不同,它有一个函数'void f(int)'并用一个引用'int'的值来调用它。 –
这与模板无关,问题依然存在。当作为函数参数传递时,变量本身始终是左值引用(无模板)。然后,根据你的函数签名,你可以创建一个对象(成为一个副本)(按值传递),或者创建一个绑定到传入引用的左值引用。 (通过参考)。但是在调用表达式中没有办法指定想要传递参数的方式。你不能同时使用'void foo(int);'和'void foo(int&)'并调用'int i = 0; foo(i)'因为它是不明确的 – DimG