我有一个非常简单的解析器规则(对于AX),如下所示:
auto space = axe::r_lit(' ');
auto spaces = space & space & space;
Run Code Online (Sandbox Code Playgroud)
最后一行在VC2010中编译并按预期工作,但在gcc 4.6中给出了一个奇怪的错误:
parsers.cpp:68:34: error: conversion from
'axe::r_and_t<
axe::r_and_t<axe::r_char_t<char>&, axe::r_char_t<char>&>,
axe::r_char_t<char>&
>' to non-scalar type
'axe::r_and_t<
axe::r_and_t<axe::r_char_t<char>&, axe::r_char_t<char>&>&,
axe::r_char_t<char>&
>' requested
Run Code Online (Sandbox Code Playgroud)
我想知道,它是否是gcc中的(已知)错误,以及是否有可能通过auto
声明获得转换错误.推导出的类型不auto
应该总是与初始化器完全相同吗?
AX 重载运算符&像这样:
template<class R1, class R2>
r_and_t<
typename std::enable_if<
is_rule<typename std::remove_reference<R1>::type>::value, R1>::type,
typename std::enable_if<
is_rule<typename std::remove_reference<R2>::type>::value, R2>::type
>
operator& (R1&& r1, R2&& r2)
{
return r_and_t<R1, R2>(std::forward<R1>(r1), std::forward<R2>(r2));
}
Run Code Online (Sandbox Code Playgroud)
我无法将问题简化为一个简短的测试用例,不幸的是每次我尝试用简单的例子来编译它.
以下包含好友声明的代码失败并显示错误(请参阅http://ideone.com/Kq5dy):
template<class T> void foo() {}
template<typename T>
class A {
void foo();
friend void foo<T>(); // error: variable or field 'foo' declared void
};
int main()
{
foo<int>();
}
Run Code Online (Sandbox Code Playgroud)
如果朋友声明和成员函数声明的顺序颠倒了,那么代码编译没有问题(参见http://ideone.com/y3hiK):
template<class T> void foo() {}
template<typename T>
class A {
friend void foo<T>();
void foo();
};
int main()
{
foo<int>();
}
Run Code Online (Sandbox Code Playgroud)
如果朋友声明不包含模板专业化,则不会发生这种情况:非模板朋友可以,以及模板朋友.在模板专门化中使用限定名称也允许编译代码.我的问题是为什么第一个例子失败了?似乎编译器在朋友声明点查找类范围中的名称,仅用于模板专业化?标准中的哪个行为被指定?
以下示例演示了我在VC++ 2010中遇到的问题:
class Foo
{
template<class T>
static T foo(T t) { return t; }
public:
void test()
{
auto lambda = []() { return foo(1); }; // call to Foo::foo<int>
lambda();
}
};
Run Code Online (Sandbox Code Playgroud)
VC++产生:错误C3861 'foo'
::标识符未找到
如果我将调用限定为foo:Foo::foo(1);
那么这个例子会编译一个警告:
警告C4573:使用'Foo::foo'
需要编译器捕获'this'
但是当前的默认捕获模式不允许它
该标准对此案有何评价?应该找到不合格的名字吗?合格的名称是否需要捕获this
?
我有一个测试类是否是解析器规则(AX解析器生成器库)的sfinae类.axe::is_rule<P>::value
如果P满足解析器规则要求,则应评估为true.解析器规则必须具有以下成员函数之一,接受一对迭代器并返回axe::result<Iterator>
:
template<class Iterator>
axe::result<Iterator> P::operator()(Iterator, Iterator);
Run Code Online (Sandbox Code Playgroud)
,或其专业化,或某些类型CharT的非模板
axe::result<CharT*> P::operator()(CharT*, CharT*);
Run Code Online (Sandbox Code Playgroud)
,或上面的const版本.从理论上讲,可能会有多个重载operator()
,但在实践中operator()
,对具有上述签名之一的单个测试就足够了.
不幸的是,目前的实施is_rule
仅涉及一些但并非所有情况.有些不幸的课程没有通过is_rule
测试:
#define AXE_ASSERT_RULE(T)\
static_assert(axe::is_rule<typename std::remove_reference<T>::type>::value, \
"type '" #T "' is not a rule");
Run Code Online (Sandbox Code Playgroud)
例如,以下不幸的类型未通过测试:
struct unfortunate
{
axe::result<const unsigned char*>
operator()(const unsigned char*, const unsigned char*);
};
AXE_ASSERT_RULE(unfortunate);
// or same using lambda
auto unfortunate1 = [](const unsigned char*, const unsigned char*)
->axe::result<const unsigned char*> {};
AXE_ASSERT_RULE(decltype(unfortunate1));
typedef std::vector<char>::iterator vc_it;
struct unfortunate2 { axe::result<vc_it> operator()(vc_it, vc_it) …
Run Code Online (Sandbox Code Playgroud) 这是我的代码:
function GetProcedureAddress(var P: FARPROC; const ModuleName, ProcName: AnsiString): Boolean;
var
ModuleHandle: HMODULE;
begin
Result := False;
ModuleHandle := GetModuleHandle(PAnsiChar(AnsiString(ModuleName)));
if ModuleHandle = 0 then
ModuleHandle := LoadLibrary(PAnsiChar(ModuleName)); // DO WE NEED TO CALL FreeLibrary ?
if ModuleHandle <> 0 then
begin
P := Pointer(GetProcAddress(ModuleHandle, PAnsiChar(ProcName)));
if Assigned(P) then
Result := True;
end;
end;
function PathMakeSystemFolder(Path: AnsiString): Boolean;
var
_PathMakeSystemFolderA: function(pszPath: PAnsiChar): BOOL; stdcall;
begin
Result := False;
if GetProcedureAddress(@_PathMakeSystemFolderA, 'shlwapi.dll', 'PathMakeSystemFolderA') then
Result := _PathMakeSystemFolderA(PChar(Path));
end;
Run Code Online (Sandbox Code Playgroud)
如果使用LoadLibrary,我们需要调用FreeLibrary吗?或者当我的申请终止时,它的引用计数会自动递减?
基本思想是创建一个可变大小的数组,在构造时固定,并在单个分配单元中创建另一个类,以减少开销并提高效率。分配一个缓冲区来容纳数组,并使用另一个对象和新的放置来构造它们。为了访问数组和另一个对象的元素,使用了指针算术和reinterpret_cast。这似乎有效(至少在 gcc 中),但我对标准(5.2.10 Reinterpret Cast)的阅读告诉我这是一种未定义的行为。那是对的吗?如果是这样,有没有办法在没有UB的情况下实现这个设计?
完整的可编译示例在这里: http: //ideone.com/C9CCa8
// a buffer contains array of A followed by B, laid out like this
// | A[N - 1] ... A[0] | B |
class A
{
size_t index;
//...
// using reinterpret_cast to get to B object
const B* getB() const
{
return reinterpret_cast<const B*>(this + index + 1);
}
};
class B
{
size_t a_count;
//...
virtual ~B() {}
// using reinterpret_cast to get to the array member
const A* …
Run Code Online (Sandbox Code Playgroud)