将包含initializer_list的参数包扩展为构造函数
Expanding parameter pack containing initializer_list to constructor
我打算在即将到来的项目中使用shared_ptr
相当多,所以(不知道std::make_shared
)我想写一个可变模板函数spnew<T>(...)
作为new
的shared_ptr
返回替身。一切都很顺利,直到我尝试使用一个构造函数包含initializer_list
的类型。当我尝试编译下面的最小示例时,我从GCC 4.5.2中得到以下内容:
奇怪的是,如果我用std::make_shared
代替spnew
,我得到了相同的错误。在任何一种情况下,当涉及initializer_list
时,它似乎都错误地推导了参数,错误地将Args...
视为空。下面是示例:
#include <memory>
#include <string>
#include <vector>
struct Example {
// This constructor plays nice.
Example(const char* t, const char* c) :
title(t), contents(1, c) {}
// This one does not.
Example(const char* t, std::initializer_list<const char*> c) :
title(t), contents(c.begin(), c.end()) {}
std::string title;
std::vector<std::string> contents;
};
// This ought to be trivial.
template<class T, class... Args>
std::shared_ptr<T> spnew(Args... args) {
return std::shared_ptr<T>(new T(args...));
}
// And here are the test cases, which don't interfere with one another.
int main(int argc, char** argv) {
auto succeeds = spnew<Example>("foo", "bar");
auto fails = spnew<Example>("foo", {"bar"});
}
这只是我的疏忽,还是一个错误?
你可以这样做-
#include <memory>
#include <string>
#include <iostream>
#include <vector>
struct Example {
template<class... Args>
Example(const char* t, Args... tail) : title(t)
{
Build(tail...);
}
template<class T, class... Args>
void Build(T head, Args... tail)
{
contents.push_back(std::string(head));
Build(tail...);
}
template<class T>
void Build(T head)
{
contents.push_back(std::string(head));
}
void Build() {}
std::string title;
std::vector<std::string> contents;
};
template<class T, class... Args>
std::shared_ptr<T> spnew(Args... args) {
return std::shared_ptr<T>(new T(args...));
}
int main(int argc, char** argv) {
auto succeeds = spnew<Example>("foo", "bar");
auto fails = spnew<Example>("foo", "bar", "poo", "doo");
std::cout << "succeeds->contents contains..." << std::endl;
for ( auto s : succeeds->contents ) std::cout << s << std::endl;
std::cout << std::endl << "fails->contents contains..." << std::endl;
for ( auto s : fails->contents ) std::cout << s << std::endl;
}
尽管泛型模板是类型安全的,但编译器会抱怨如果传递的类型不能转换为const char *
,则为contents.push_back
。
如上所述,您的代码在gcc 4.6下工作得很好,但是您得到的警告在这里解释why- not -my-template-accept-an-initializer-list,并且可能不是标准兼容,尽管c++0x标准尚未发布,所以这可能会改变。
对于gcc-4.7(可能也可以在gcc-4.6上工作,只是分支),警告:
foo.cpp: In function ‘int main(int, char**)’:
foo.cpp:29:47: warning: deducing ‘Args ...’ as ‘std::initializer_list<const
char*>’ [enabled by default]
foo.cpp:22:20: warning: in call to ‘std::shared_ptr<_Tp1> spnew(Args ...)
[with T = Example, Args = {const char*, std::initializer_list<const
char*>}]’ [enabled by default]
foo.cpp:29:47: warning: (you can disable this with -fno-deduce-init-list)
[enabled by default]
我不知道为什么有人会抱怨初始列表的演绎。
有一个相关的线程:为什么我的模板不接受初始化列表
基本上,一个裸初始化列表没有类型
相关文章:
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 为什么在没有显式默认构造函数的情况下,将另一个结构封装在联合中作为成员的结构不能编译
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- 选择要调用的构造函数
- 如何委托派生类使用其父构造函数?
- 构造函数正在调用一个使用当前类类型的函数
- 为什么我不能在 c++ 类中声明一个空构造函数,该构造函数从一个具有私有构造函数的构造函数扩展而来
- 通过添加构造函数和一些成员函数来扩展 std::(w)字符串
- 我无法在不违反 c++ 扩展规则的情况下制作匹配的构造函数
- Ruby C++扩展中的多个构造函数
- 如果在构造函数中使用宏,它可以以不同的方式扩展吗?
- 扩展具有私有构造函数和析构函数的单例类会给出编译时警告
- Node.js 的本机 c++ 扩展:"cloning"构造函数中的本地<值>
- 从php扩展中调用对象构造函数(__construct)
- MSVC直接构造函数调用扩展
- 编译器的区别:扩展x3::变体需要用gcc定义复制构造函数、复制赋值运算符和默认构造函数,但不需要clang
- 同一类的 C++ 扩展构造函数(无继承)
- 将包含initializer_list的参数包扩展为构造函数