Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/141.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么这个编译,模板演绎应该失败?_C++_Templates_C++11 - Fatal编程技术网

C++ 为什么这个编译,模板演绎应该失败?

C++ 为什么这个编译,模板演绎应该失败?,c++,templates,c++11,C++,Templates,C++11,我正在尝试编写一个序列化程序。编译以下代码: #include <string> #include <fstream> #include <type_traits> #include <map> #include <iostream> class SpaceStream { public: SpaceStream(const std::string& filename) : m_file(fi

我正在尝试编写一个序列化程序。编译以下代码:

#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);
}
因为有两个
Add
函数,一个专门检查类型是否为类,另一个检查类型是否为引用,因此可能会失败
m_rx
是一种参考类型,所以它应该失败吗

编辑 我现在明白了,类型实际上是一个值,而不是一个引用。我需要能够识别引用,以便跟踪它们(我只想序列化数据一次,然后引用它)。

根据

如果表达式最初具有类型“reference to T”([dcl.ref]、[dcl.init.ref]),则在进行任何进一步分析之前,该类型将调整为T。表达式指定由引用表示的对象或函数,表达式是左值或x值,具体取决于表达式。[注意:在引用的生存期开始之前或结束之后,行为是未定义的(请参见[basic.life])。-结束注意]

我认为在执行模板参数推断时,参数类型
A
永远不会是引用类型。一个简单的测试可能是

#include <type_traits>    

template <class T> void f(T) { static_assert(std::is_same<T, int &>::value, "ERROR"); } 
template <class T> void ff(T) { static_assert(std::is_same<T, int>::value, "ERROR"); }   

int main(int argc, const char **argv) {
    int i;
    int &r = i;
    f(r); // static assert failed
    ff(r); // static assert success
    return 0;
}

“我认为参数类型A在执行模板参数推断时永远不会是引用类型”,转发引用除外type@PiotrSkotnicki我没有完全理解你的意思。如果您的意思是
std::forward
,则根本没有模板参数推导,因为我们需要在使用它时显式地提供模板参数。至于转发引用类型推断,
A
部分仍然不能是引用类型。“我需要能够识别引用以便跟踪它们”你的意思是什么?这与使用函数
void f(int)没有什么区别
并使用引用
int
的值调用它。这与模板无关,没有模板问题依然存在。当作为函数参数传递时,变量本身始终是左值引用(无模板)。然后,根据函数签名,您可以创建一个对象(成为副本)(按值传递)或创建一个绑定到传递的引用的左值引用。(通过引用传递)。但无法在调用表达式时指定您希望如何传递参数。不能有
void foo(int)
voidfoo(int&)
同时调用
inti=0;foo(i)
因为它不明确
#include <type_traits>    

template <class T> void f(T) { static_assert(std::is_same<T, int &>::value, "ERROR"); } 
template <class T> void ff(T) { static_assert(std::is_same<T, int>::value, "ERROR"); }   

int main(int argc, const char **argv) {
    int i;
    int &r = i;
    f(r); // static assert failed
    ff(r); // static assert success
    return 0;
}
f<decltype(r)>(r); // static assert success now