我正在尝试实现一个类似于std::transform算法的函数,而不是通过我想创建的参数获取输出迭代器,并返回一个带有转换输入元素的容器.
让我们说它的名称transform_container并带有两个参数:容器和仿函数.它应返回相同的容器类型,但可能由不同的元素类型进行参数化(Functor可以返回不同类型的元素).
我想使用我的函数,如下例所示:
std::vector<int> vi{ 1, 2, 3, 4, 5 };
auto vs = transform_container(vi, [] (int i) { return std::to_string(i); });
//vs will be std::vector<std::string>
assert(vs == std::vector<std::string>({"1", "2", "3", "4", "5"}));
std::set<int> si{ 5, 10, 15 };
auto sd = transform_container(si, [] (int i) { return i / 2.; });
//sd will be of type std::set<double>
assert(sd == std::set<double>({5/2., 10/2., 15/2.}));
Run Code Online (Sandbox Code Playgroud)
我能够写两个函数 - 一个for std::set和one for std::vector- 似乎正常工作.它们是相同的,除了容器类型名称.他们的代码如下所示.
template<typename T, typename Functor> …Run Code Online (Sandbox Code Playgroud) 考虑以下:
template<typename Der>
struct Base {
// NOTE: if I replace the decltype(...) below with auto, code compiles
decltype(&Der::operator()) getCallOperator() const {
return &Der::operator();
}
};
struct Foo : Base<Foo> {
double operator()(int, int) const {
return 0.0;
}
};
int main() {
Foo f;
auto callOp = f.getCallOperator();
}
Run Code Online (Sandbox Code Playgroud)
我想在CRTP基类中创建一个成员函数,其返回类型取决于operator()派生类中的签名.但decltype(&Der::operator())无法编译; 将operator()在成员函数Foo是不可见的.我假设这是因为基类模板在Foo完全定义之前被实例化.
令人惊讶的是,如果我auto为返回类型放置它编译.我假设这auto会使编译器从函数体中推导出返回类型并失败 - 因为正文使用了未完全定义的Foo类型.
MSVC 2015.3和Clang 3.8的行为相同
为什么代码开始使用auto?难道auto类型推演莫名其妙"延迟"的实例?或者使用与手写返回类型表达式不同的上下文?
我想问一下下面的代码示例是否应该编译:
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
template <template <class...> class C>
struct convert_container
{
using type = C<double>;
// Visual Studio requires this to be:
// using type = C<double, std::allocator<doble>>
};
int main()
{
std::cout << typeid(convert_container<std::vector>::type).name();
}
Run Code Online (Sandbox Code Playgroud)
代码可以使用GCC 4.8.1和Clang 3.4编译,但不适用于Visual Studio 2013.我得到的错误:
error C2976: 'std::vector' : too few template arguments
c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see declaration of 'std::vector'
c:\users\micha?\documents\visual studio 2013\projects\transform\transform.cpp(14) : see reference to class template instantiation 'convert_container<std::vector>' being compiled …Run Code Online (Sandbox Code Playgroud)