【问题标题】:Call template function for the value of a pointer out of a template function, in C++在 C++ 中为模板函数中的指针值调用模板函数
【发布时间】:2015-06-15 09:30:43
【问题描述】:

我正在尝试为在我的调用函数中作为模板参数给出的指针调用模板函数。我的代码是:

template <>
struct serialize_helper<std::string> {
     // not important code...
    }

};

template <class T>
inline void serializer(const T& obj, StreamType::iterator& res) {

    if(std::is_pointer<T>::value)
    {
        //THIS doesn' work
        serialize_helper<*T>::apply(*obj,res);
    }
    else
        serialize_helper<T>::apply(obj,res);

}

如果我打电话:

std::string test("test");
serializer(test, res);

一切正常。 但我也希望能够使用指针作为 obj 调用序列化程序:

std::string test* = new std::string("test");
serializer(test, res);

在调用序列化程序函数之前取消引用指针是不可能的选择,请不要这样做。在序列化器函数内部是可能的。

简短的描述:我想用std::string* 调用serializer,如果我用它指向的std::string 调用它,它会做同样的事情。

【问题讨论】:

  • 请提供MCVE 以及您遇到的错误消息。

标签: c++ templates pointers c++11


【解决方案1】:

模板函数的整个主体都需要针对它实例化的类型进行编译,无论是否会采用分支。为了解决这个问题,您可以为 T 何时为指针以及何时不是指针定义单独的函数。

使用 SFINAE:

template <class T, std::enable_if_t<std::is_pointer<T>::value>* = nullptr>
inline void serializer(const T& obj, StreamType::iterator& res) {
    serialize_helper<std::remove_pointer_t<T>>::apply(*obj,res);
}

template <class T, std::enable_if_t<!std::is_pointer<T>::value>* = nullptr>
inline void serializer(const T& obj, StreamType::iterator& res) {
    serialize_helper<T>::apply(obj,res);
}

使用标记调度:

template <class T>
inline void serializer(const T& obj, StreamType::iterator& res, std::true_type) {
    serialize_helper<std::remove_pointer_t<T>>::apply(*obj,res);
}

template <class T>
inline void serializer(const T& obj, StreamType::iterator& res, std::false_type) {
    serialize_helper<T>::apply(obj,res);
}

template <class T>
inline void serializer(const T& obj, StreamType::iterator& res) {
    serializer(obj, res, std::is_pointer<T>());
}

【讨论】:

  • 我用你的第二个例子明白了,但我使用:serialize_helper::type>::apply(*obj, res);而不是 serialize_helper<:remove_pointer>::type>::apply(*obj, res);
【解决方案2】:

我会选择类似的东西

template <class T>
inline void serializer(const T& obj, StreamType::iterator& res) {
    serialize_helper<T>::apply(obj,res);
}

template<class T>
inline void serializer(T* obj, StreamType::iterator& res) {
    serialize_helper<T>::apply(*obj,res);
}

【讨论】:

  • @StheKing 也适合我。 An exemple 看起来更像你的情况。
【解决方案3】:

您可以使用std::remove_pointerstd::enable_if 来做到这一点。

template <class T, typename std::enable_if<std::is_pointer<T>::value>::type* = nullptr>
inline void serializer(const T& obj) {
    serialize_helper<typename std::remove_pointer<T>::type>::apply(*obj);
}

template <class T, typename std::enable_if<!std::is_pointer<T>::value>::type* = nullptr>
inline void serializer(const T& obj) {
    serialize_helper<T>::apply(obj);
}

请注意,为简单起见,我删除了 StreamType

live demo

【讨论】:

  • 我认为在 C++14 中应该是 typename std::remove_pointer&lt;T&gt;::typestd::remove_pointer_t&lt;T&gt;
  • 好点!我仍然需要在这方面进行一些练习,但我的编辑应该会带来一些不错的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-18
  • 2014-03-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多