C++ C++;名称相同但返回类型不同的模板函数
我试图使一些文件流光,可以读取或写入不同的类型。除了有特定方法的阅读部分外,其他一切都正常。该方法在调用时返回C++ C++;名称相同但返回类型不同的模板函数,c++,templates,C++,Templates,我试图使一些文件流光,可以读取或写入不同的类型。除了有特定方法的阅读部分外,其他一切都正常。该方法在调用时返回std::unique_ptr,是另一个返回T的方法的“包装器”。出于某种原因,编译器不使用此方法,而是尝试使用另一个方法(返回T)对其进行编译。因此编译失败。我已经试着在互联网上搜索,但我找不到任何准确的答案。你能帮我做这个吗 我定义的两种方法: template <typename T> T read() { T obj; obj.readFromFi
std::unique_ptr
,是另一个返回T
的方法的“包装器”。出于某种原因,编译器不使用此方法,而是尝试使用另一个方法(返回T
)对其进行编译。因此编译失败。我已经试着在互联网上搜索,但我找不到任何准确的答案。你能帮我做这个吗
我定义的两种方法:
template <typename T>
T read()
{
T obj;
obj.readFromFile<T>();
return std::move(obj);
}
模板
T read()
{
T-obj;
obj.readFromFile();
返回标准::移动(obj);
}
及
模板<
类型名T,
模板类别D,
模板类容器
>
typename std::启用\u如果\u t<
std::值是否相同,
容器
>
读()
{
返回std::move(std::make_unique(readFromFile());
}
后一种方法就是我试图调用的方法
当我这样写的时候:
std::unique\ptr AfromFile=fileStreamer.read()
编译器尝试使用第一个方法(template T read(){…}
)编译它,但编译失败。如果我先创建了唯一的\u ptr对象
,然后对*唯一的\u ptr对象
执行复制赋值,我就可以实现这一点,但这对我没有好处,因为我在这两个函数上使用了一些宏,在调用宏之前,我无法创建唯一的\u ptr对象
或对象本身。仅供参考,我正在使用Visual Studio 2015
有没有办法不做任何重大修改就完成这项工作?我还发现了一个建议,基本上说您必须向一个函数添加一个指针参数,然后使用static\u cast(nullptr)
作为参数调用它,但这在我的示例中不算
谢谢你的帮助
更新:
我只想说一句,下面所有的解决方案都对我有效,但是解决我的问题最简单的方法是Barry提供的解决方案。
再次感谢你帮助我 似乎您需要部分专门化,并且由于函数的部分专门化是不可能的,您可以转发到类:
template <typename T> struct helper
{
T operator() const
{
T obj;
obj.readFromFile<T>();
return obj;
}
};
template <typename T, typename D>
struct helper<std::unique_ptr<T, D>>
{
std::unique_ptr<T, D> operator() const
{
return std::make_unique<T, D>(readFromFile<T>());
}
};
template <typename T>
T read()
{
return helper<T>{}();
}
模板结构帮助器
{
T运算符()常量
{
T-obj;
obj.readFromFile();
返回obj;
}
};
模板
结构辅助程序
{
std::unique_ptr运算符()常量
{
return std::make_unique(readFromFile());
}
};
模板
T read()
{
返回帮助程序{}();
}
问题在于,尽管我理解您的意图:
std::unique_ptr<A> AfromFile = fileStreamer.read<std::unique_ptr<A>>();
第一个有一个模板参数,第二个有3个(和一些sfinae)。但是您只使用一个模板参数调用read()
,因此第二个重载(您想要的重载)甚至不是一个选项
对于这些情况,我喜欢简单地标记分派,这样我们就可以过载,而不必专门化:
template <class T> struct tag{};
template <class T> T read() { return read(tag<T>{}); }
template <class T>
T read(tag<T> ) {
T obj;
obj.readFromFile<T>();
return obj; // <== NB: no move() here! That inhibits RVO
}
template <class T, class D>
std::unique_ptr<T, D> read(tag<std::unique_ptr<T, D>> ) {
/* unique_ptr case */
}
模板结构标记{};
模板T read(){返回读取(标记{});}
模板
T读取(标签){
T-obj;
obj.readFromFile();
返回obj;//
一个函数不能有两个只因返回类型不同而不同的重载。必须使用SFINAE确保对任何给定模板参数只启用一个重载
在第二个重载中,您试图推断模板参数的方式是错误的。目前,在调用函数时,您必须指定T
、D
和ContainerType
。我感觉您可能只想传递一个类型,然后推断它是否是std::unique\u ptr
不能调用std::make_unique
并指定删除器类型。必须使用新创建的对象调用std::unique_ptr
构造函数
您不需要显式移动返回的std::unique\u ptr
这是做你想做的事情的一种方法
#include <memory>
#include <type_traits>
template<typename T>
T readFromFile() { return T(); }
template<typename T, typename D>
void helper(std::unique_ptr<T, D>);
template<typename T, typename = void>
struct is_unique_ptr : std::false_type {};
template<typename T>
struct is_unique_ptr<T, decltype(helper(std::declval<T>()))> : std::true_type {};
template<typename T, typename = std::enable_if_t<!is_unique_ptr<T>::value>>
T read()
{
return readFromFile<T>();
}
template<typename P, typename = std::enable_if_t<is_unique_ptr<P>::value>, typename = void>
P read()
{
using T = typename P::element_type;
return P(new T(readFromFile<T>()));
}
int main()
{
read<std::unique_ptr<int>>();
read<int>();
}
#包括
#包括
模板
T readFromFile(){返回T();}
模板
void helper(std::unique_ptr);
模板
结构是唯一的\u ptr:std::false\u type{};
模板
结构是唯一的\u ptr:std::true\u类型{};
模板>
T read()
{
返回readFromFile();
}
模板
P read()
{
使用T=typename P::element\u type;
返回P(新的T(readFromFile());
}
int main()
{
read();
read();
}
您必须调用fileStreamer.read()
…你是对的,事实上我调用这个方法时使用了错误的参数数。在我像你建议的那样输入了正确的参数数之后,代码编译器感谢你的建议。这个解决方案是解决我问题的最简单的方法。哦,我使用std::move,因为我希望所有对象都应该有move/assign构造函数。
template <class T> struct tag{};
template <class T> T read() { return read(tag<T>{}); }
template <class T>
T read(tag<T> ) {
T obj;
obj.readFromFile<T>();
return obj; // <== NB: no move() here! That inhibits RVO
}
template <class T, class D>
std::unique_ptr<T, D> read(tag<std::unique_ptr<T, D>> ) {
/* unique_ptr case */
}
#include <memory>
#include <type_traits>
template<typename T>
T readFromFile() { return T(); }
template<typename T, typename D>
void helper(std::unique_ptr<T, D>);
template<typename T, typename = void>
struct is_unique_ptr : std::false_type {};
template<typename T>
struct is_unique_ptr<T, decltype(helper(std::declval<T>()))> : std::true_type {};
template<typename T, typename = std::enable_if_t<!is_unique_ptr<T>::value>>
T read()
{
return readFromFile<T>();
}
template<typename P, typename = std::enable_if_t<is_unique_ptr<P>::value>, typename = void>
P read()
{
using T = typename P::element_type;
return P(new T(readFromFile<T>()));
}
int main()
{
read<std::unique_ptr<int>>();
read<int>();
}