- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在下面的代码中,我使用了一种相对简单的类型删除技术。 interpreter_context_ptr
类定义了一个“接口(interface)”,指向实现该接口(interface)的对象的指针可用于构造一个interpreter_context_ptr
。这允许在不使用虚拟分派(dispatch)的情况下实现多态。
这与一篇名为Impossibly Fast Delegates的旧文章极其相似.另外,查看 eraserface badair 在 github 上的项目。
还有,如果你一开始不认识,这里的+[](...)
语法就是所谓的“positive lambda”语法,here很好的解释。
这是 MCVE:
#include <iostream>
#include <string>
#include <vector>
class interpreter_context_ptr {
void * object_;
void (*new_text_call_)(void *, const std::string &);
void (*error_text_call_)(void *, const std::string &);
void (*clear_input_call_)(void *);
public:
void new_text(const std::string & str) const {
this->new_text_call_(object_, str);
}
void error_text(const std::string & str) const {
this->error_text_call_(object_, str);
}
void clear_input() const { this->clear_input_call_(object_); }
template <typename T>
explicit interpreter_context_ptr(T * t)
: object_(static_cast<void *>(t))
, new_text_call_(+[](void * o, const std::string & str) {
static_cast<T *>(o)->new_text(str);
})
, error_text_call_(+[](void * o, const std::string & str) {
static_cast<T *>(o)->error_text(str);
})
, clear_input_call_(+[](void * o) { static_cast<T *>(o)->clear_input(); }) {
}
};
/***
* Tests
*/
struct A {
void new_text(const std::string & str) {
std::cout << "A: " << str << std::endl;
}
void error_text(const std::string & str) {
std::cout << "A! " << str << std::endl;
}
void clear_input() { std::cout << std::endl; }
};
struct B {
void new_text(const std::string & str) {
std::cout << "B: " << str << std::endl;
}
void error_text(const std::string & str) {
std::cout << "B! " << str << std::endl;
}
void clear_input() { std::cout << std::endl; }
};
int main() {
std::vector<interpreter_context_ptr> stack;
A a;
B b;
stack.emplace_back(&a);
stack.back().new_text("1");
stack.emplace_back(&b);
stack.back().new_text("2");
stack.emplace_back(&b);
stack.back().new_text("3");
stack.back().clear_input();
stack.pop_back();
stack.back().error_text("4");
stack.emplace_back(&a);
stack.back().error_text("5");
stack.pop_back();
stack.back().error_text("6");
stack.pop_back();
stack.back().new_text("7");
stack.back().clear_input();
stack.pop_back();
std::cout << "Stack size = " << stack.size() << std::endl;
}
被测代码非常简单,只有几行,在我最近几个月做的一个项目中,在gcc和clang中运行良好。
但是,我从 MSVC 收到了一些我不理解的非常简洁的错误消息。
首先,它提示正 lambda,我认为它不应该这样。(我从 rextester.com 粘贴这些错误)
Error(s):
source_file.cpp(27): error C2061: syntax error: identifier 'T'
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(655): note: see reference to function template instantiation 'interpreter_context_ptr::interpreter_context_ptr<A>(T *)' being compiled
with
[
T=A
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(773): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,A>(_Objty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(773): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,A>(_Objty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(918): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,A>(std::allocator<_Ty> &,_Objty *,A &&)' being compiled
with
[
_Alloc=std::allocator<interpreter_context_ptr>,
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(917): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,A>(std::allocator<_Ty> &,_Objty *,A &&)' being compiled
with
[
_Alloc=std::allocator<interpreter_context_ptr>,
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(929): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<interpreter_context_ptr,A>(_Ty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(928): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<interpreter_context_ptr,A>(_Ty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
source_file.cpp(68): note: see reference to function template instantiation 'void std::vector<interpreter_context_ptr,std::allocator<_Ty>>::emplace_back<A*>(A *&&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
source_file.cpp(68): note: see reference to function template instantiation 'void std::vector<interpreter_context_ptr,std::allocator<_Ty>>::emplace_back<A*>(A *&&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
source_file.cpp(28): error C2593: 'operator +' is ambiguous
source_file.cpp(28): note: could be 'built-in C++ operator+(void (__cdecl *)(void *,const std::string &))'
source_file.cpp(28): note: or 'built-in C++ operator+(void (__stdcall *)(void *,const std::string &))'
source_file.cpp(28): note: or 'built-in C++ operator+(void (__fastcall *)(void *,const std::string &))'
source_file.cpp(28): note: or 'built-in C++ operator+(void (__vectorcall *)(void *,const std::string &))'
source_file.cpp(28): note: while trying to match the argument list '(interpreter_context_ptr::<lambda_3268dba1ab087602b708c8fa2c92932b>)'
source_file.cpp(30): error C2061: syntax error: identifier 'T'
source_file.cpp(31): error C2593: 'operator +' is ambiguous
source_file.cpp(31): note: could be 'built-in C++ operator+(void (__cdecl *)(void *,const std::string &))'
source_file.cpp(31): note: or 'built-in C++ operator+(void (__stdcall *)(void *,const std::string &))'
source_file.cpp(31): note: or 'built-in C++ operator+(void (__fastcall *)(void *,const std::string &))'
source_file.cpp(31): note: or 'built-in C++ operator+(void (__vectorcall *)(void *,const std::string &))'
source_file.cpp(31): note: while trying to match the argument list '(interpreter_context_ptr::<lambda_b251fc93653023678ada88e17e2a71b3>)'
source_file.cpp(32): error C2061: syntax error: identifier 'T'
source_file.cpp(32): error C2593: 'operator +' is ambiguous
source_file.cpp(32): note: could be 'built-in C++ operator+(void (__cdecl *)(void *))'
source_file.cpp(32): note: or 'built-in C++ operator+(void (__stdcall *)(void *))'
source_file.cpp(32): note: or 'built-in C++ operator+(void (__fastcall *)(void *))'
source_file.cpp(32): note: or 'built-in C++ operator+(void (__vectorcall *)(void *))'
source_file.cpp(32): note: while trying to match the argument list '(interpreter_context_ptr::<lambda_3ba87b1970191b4772ddfa67a05f70ea>)'
source_file.cpp(28): error C2088: '+': illegal for class
source_file.cpp(31): error C2088: '+': illegal for class
source_file.cpp(32): error C2088: '+': illegal for class
好吧,微软的“正 lambda”理论有问题,其中 lambda 被隐式转换为函数指针,而一元 operator +
是空操作。没关系,让我们去掉正 lambda。
template <typename T>
explicit interpreter_context_ptr(T * t)
: object_(static_cast<void *>(t))
, new_text_call_([](void * o, const std::string & str) {
static_cast<T *>(o)->new_text(str);
})
, error_text_call_([](void * o, const std::string & str) {
static_cast<T *>(o)->error_text(str);
})
, clear_input_call_([](void * o) { static_cast<T *>(o)->clear_input(); }) {
}
原来 MSVC 仍然不满意——主要错误是神秘的 C2061 .
The compiler found an identifier where it wasn't expected. Make sure that identifier is declared before you use it.
An initializer may be enclosed by parentheses. To avoid this problem, enclose the declarator in parentheses or make it a typedef.
This error could also be caused when the compiler detects an expression as a class template argument; use typename to tell the compiler it is a type.
这是完整的日志:
Error(s):
source_file.cpp(27): error C2061: syntax error: identifier 'T'
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(655): note: see reference to function template instantiation 'interpreter_context_ptr::interpreter_context_ptr<A>(T *)' being compiled
with
[
T=A
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(773): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,A>(_Objty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(773): note: see reference to function template instantiation 'void std::allocator<_Ty>::construct<_Objty,A>(_Objty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(918): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,A>(std::allocator<_Ty> &,_Objty *,A &&)' being compiled
with
[
_Alloc=std::allocator<interpreter_context_ptr>,
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(917): note: see reference to function template instantiation 'void std::allocator_traits<_Alloc>::construct<_Ty,A>(std::allocator<_Ty> &,_Objty *,A &&)' being compiled
with
[
_Alloc=std::allocator<interpreter_context_ptr>,
_Ty=interpreter_context_ptr,
_Objty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(929): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<interpreter_context_ptr,A>(_Ty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(928): note: see reference to function template instantiation 'void std::_Wrap_alloc<std::allocator<_Ty>>::construct<interpreter_context_ptr,A>(_Ty *,A &&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
source_file.cpp(68): note: see reference to function template instantiation 'void std::vector<interpreter_context_ptr,std::allocator<_Ty>>::emplace_back<A*>(A *&&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
source_file.cpp(68): note: see reference to function template instantiation 'void std::vector<interpreter_context_ptr,std::allocator<_Ty>>::emplace_back<A*>(A *&&)' being compiled
with
[
_Ty=interpreter_context_ptr
]
source_file.cpp(30): error C2061: syntax error: identifier 'T'
source_file.cpp(32): error C2061: syntax error: identifier 'T'
我尝试了他们的建议,将 typename
放在 T
之前的所有地方,但没有任何帮助,而且我没有收到任何更多信息性错误消息。
这里有什么故事? C2061“标识符”错误在这里是什么意思,这意味着 MSVC 无法跟踪 lambda 主体内部的模板参数,或者它解析错误并认为 T
是一个变量并且不是类型之类的?
像 MSVC 2015 这样的模板函数中的 lambda 是不可能引用模板参数的吗?
我是否只需要分解出 lambda 并改为创建更多静态模板函数?
事实证明,如果我完全摆脱 lambda 表达式并像这样使用模板函数,那么 MSVC 会很好地编译它:
class interpreter_context_ptr {
void * object_;
void (*new_text_call_)(void *, const std::string &);
void (*error_text_call_)(void *, const std::string &);
void (*clear_input_call_)(void *);
template <typename T>
struct helper {
static void new_text(void * o, const std::string & str) {
static_cast<T*>(o)->new_text(str);
}
static void error_text(void * o, const std::string & str) {
static_cast<T*>(o)->error_text(str);
}
static void clear_input(void * o) {
static_cast<T*>(o)->clear_input();
}
};
public:
void new_text(const std::string & str) const {
this->new_text_call_(object_, str);
}
void error_text(const std::string & str) const {
this->error_text_call_(object_, str);
}
void clear_input() const { this->clear_input_call_(object_); }
template <typename T>
explicit interpreter_context_ptr(T * t)
: object_(static_cast<void *>(t))
, new_text_call_(&helper<T>::new_text)
, error_text_call_(&helper<T>::error_text)
, clear_input_call_(&helper<T>::clear_input) {
}
};
但正如我在评论中所写,如果我真的必须走这么远,我会感到非常惊讶。 MSVC 开发人员声称已在 this C++11 feature page 上完全支持和实现 lambda 函数.我认为这应该包括能够在 lambda 范围内引用环境模板参数。
最佳答案
在提出这个问题时,Visual C++ 2015 编译器在 lambda 上遇到 operator+
问题。删除每个 lambda 前面的 +
符号可以编译。它确实稍微改变了语义(表达式的有效类型略有不同),但我认为这在这里并不重要。
确保您安装了最新的更新,以确保没有其他编译器/库错误让您无缘无故地浪费时间。
关于c++ - 类型删除、委托(delegate)和 lambda 函数与 msvc,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40628731/
我有两个单独编译的DLL,一个是从Visual Studio2008编译的,另一个是从MATLAB编译的MEX文件。这两个DLL都包含一个头文件。当我获取一个DLL中的结构sizeof()时,它返回4
一位同事更喜欢尤达的条件:。这在团队中是一种有争议的风格,并且提出的一个论点是,如果(x=0),编译器可以一致地发出警告来检测错误模式。。然而,msvc似乎没有检测到类(https://godbolt
while (getline(stream, thisword, ' ') != 0) {... 我可以在 MSVC 2012 下编译这一行。通过传递一个“SPC”字符作为字符串分隔符,它应该测试输入
我使用较早版本的 Cocos2dx 编写游戏并使用 VS 2013 对其进行编译。请注意,我使用的是 CMake 和 Qt Creator 以及两个编译器版本。当 Cocos2dx v3.12 出来时
我正在尝试在 Windows 10 64 位下的 Python 3.8.3 上安装 chatterbot 包并遇到一个奇怪的错误,我怀疑它一定与某些目录或 PATH 设置有关,我希望这是一个简单的修复
知乎Where and why do we have to put the template and typename keywords , 我很惊讶地得知 MSVC accepts以下代码: str
在摆弄复制省略时,我遇到了这种奇怪的行为: class Obj { public: Obj() = default; Obj(Obj&&) = delete; Obj(const Obj
以下代码使用 gcc 和 clang(以及许多其他 C++11 编译器)进行编译 #include typedef int datatype; template struct to_datatyp
我已经阅读了很多帖子,但我不明白如何在命令行中使用 MSVC 在 Windows 上创建一个简单的动态库。我正在做的是: 1º) 编写 DLL 代码 动态.h #pragma once __decls
我有以下代码无法与MSVC一起编译。使用gcc,clang和icc可以正常编译。我想这是个错误,对不对? 您有/知道一些解决方法吗? #include struct A { template
我已经阅读了很多帖子,但我不明白如何在命令行中使用 MSVC 在 Windows 上创建一个简单的动态库。我正在做的是: 1º) 编写 DLL 代码 动态.h #pragma once __decls
我有一个简单的 C++ 代码,我尝试使用 Visual Studio 2019 进行编译: #include #include int main() { std::cout << "Hel
有没有办法告诉MSVC编译器在短时间内不要修改某个寄存器?就像在一个小循环中,告诉它不要使用 ebx 寄存器(它可以使用任何其他寄存器)。在这种情况下,压入和弹出寄存器不起作用,因为在我将其弹出后,M
Borland C 有伪寄存器 _AX、_BX、_FLAGS 等,可以在“C”代码中使用它们将寄存器保存到临时变量。 是否有任何 MSVC 等效项?我尝试了@AX、@BX等,但编译器(MSVC1.5)
美好的一天, 我在 C++ 中尝试新事物,我发现 Visual Studio 中的调试和发布配置给我不同的结果。 #include #include #include #include #in
我想我在 MSVC 的编译器(MSVC Ultimate 2012 版本 11.0.61030.00 更新 4)中发现了一个错误。 #include "stdafx.h" class Base { p
我正在使用 Haxe 的 HXCPP 生成 C++ 代码并使用 Microsoft Visual Studio 2010 Express Edition 对其进行编译。我正在关注 this指南,它会要
我正在使用 Microsoft Visual Studio 2008 (C++)。我有一个要在 Debug模式下构建的解决方案。我引用了一些第三方库(例如 MyGUI)。在调试构建结束时,链接器给出了
老计算机程序员遇到新问题:-) 我正在将一个 CMake 文件项目移至 Visual Studio,并且该 CMake 项目中有数百个包含路径。 我当然可以一劳永逸地修补它们,但这会经常发生在不同的机
我有下一个功能: namespace TEST { class TEST { int a; int b; }; } namespace UNION_TE
我是一名优秀的程序员,十分优秀!