请考虑以下代码段:
void Foo() // 1
{
}
namespace
{
void Foo() // 2
{
}
}
int main()
{
Foo(); // Ambiguous.
::Foo(); // Calls the Foo in the global namespace (Foo #1).
// I'm trying to call the `Foo` that's defined in the anonymous namespace (Foo #2).
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如何引用匿名命名空间内的内容?
我希望这个标题能够真正描述我想要问的内容......
我编写了一段代码,用gcc编译并按照我的意图工作.但是,它不使用llvm编译,并且在使用icc编译时代码执行方式不同!
以下是问题的示例:
#include <iostream>
using std::cout; using std::endl;
class A {
public:
virtual void foo() { cout << "A::foo()" << endl; }
};
class B : public A {
public:
typedef A base;
virtual void foo() { cout << "B::foo()" << endl; }
};
int main() {
typedef B base;
base* bp = new B();
bp->base::foo();
}
Run Code Online (Sandbox Code Playgroud)
gcc输出:A :: foo()
icc输出:B :: foo()
有人可以解释标准对这个案子的看法吗?
#include <iostream>
using namespace std;
struct test
{
test(){cout<<"class"<<endl;}
};
void test(){cout<<"function"<<endl;}
int main()
{
test();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
function
Run Code Online (Sandbox Code Playgroud)
(VS2013 ang gcc 4.8.1)
为什么选择功能?是不是模棱两可?
我今天遇到了这个,我很惊讶我之前没有注意到它.给出一个简单的C#程序,类似于以下内容:
public class Program
{
public static void Main(string[] args)
{
Method(); // Called the method with no arguments.
Method("a string"); // Called the method with a string.
Console.ReadLine();
}
public static void Method()
{
Console.WriteLine("Called the method with no arguments.");
}
public static void Method(string aString = "a string")
{
Console.WriteLine("Called the method with a string.");
}
}
Run Code Online (Sandbox Code Playgroud)
您将获得每个方法调用的注释中显示的输出.
我理解为什么编译器会选择它所做的重载,但为什么首先允许这样做呢?我不是在问什么是重载决策规则,我理解这些规则,但我想知道是否存在技术上的原因,为什么编译器允许基本上具有相同签名的两个重载?
据我所知,一个带有签名的函数重载只是通过另外一个可选参数与另一个重载不同,只提供了如果只需要参数(和所有前面的参数).
它所做的一件事是让程序员(可能没有给予足够的重视)认为他们正在调用与他们实际存在的不同的重载.
我想这是一个相当罕见的情况下,以及为什么这是允许的可能只是因为它根本不值得的复杂性,以禁止它的答案,但有另一个原因,C#允许函数重载从其他人的不同仅通过有一个附加的可选争论?
这段代码怎么可能
TaskManager.RunSynchronously<MyObject>(fileMananager.BackupItems, package);
Run Code Online (Sandbox Code Playgroud)
导致编译错误
The call is ambiguous between the following methods or properties:
'TaskManager.RunSynchronously<MyObject>(System.Action<MyObject>, MyObject)' and
'TaskManager.RunSynchronously<MyObject>(System.Func<MyObject, bool>, MyObject)'
Run Code Online (Sandbox Code Playgroud)
当行动的签名是
public void BackupItems(MyObject package)
Run Code Online (Sandbox Code Playgroud)
和"暧昧"的方法是
static class TaskManager
{
public static void RunSynchronously<TInput>(Action<TInput> task, TInput param)
{
Task.Factory.StartNew(() => task(param));
}
public static bool RunSynchronously<TInput>(Func<TInput, bool> task, TInput param)
{
return Task.Factory.StartNew(() => task(param)).Result;
}
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这些方法之间存在很大差异.我在这里错过了什么?
编辑:
除了接受的答案,我刚刚遇到了类似问题的解决方案.这是链接.
我对上下文敏感度和模糊性如何相互影响感到困惑.
我认为是正确的是:
歧义:
模糊语法导致使用左或右派生构造多个解析树.所有可能的语法都含糊不清的语言是一种含糊不清的语言.
例如,C++是一种含糊不清的语言,因为x*y总是意味着两种不同的东西,如下所述:为什么不能用LR(1)解析器解析C++?.
上下文灵敏度:
上下文敏感语法具有规则,其中这些规则的左侧可以包含(非)终端符号,除了在不同类型语法的所有规则的lhs内所需的一个非终结符号之外.这意味着您不能在降序时替换非终结符.相反,你必须先看看周围的非终结者.
现在困扰我的是那些或多或少说上下文敏感的解析器可以解析像x*y这样的歧义的语句.例如,在上面的链接问题中,声明"... [在创建语法树时装饰语法树]的解析器不是上下文无关的,而LR解析器(纯粹的解析器)是无上下文的." 在我看来,这意味着上下文敏感的解析器(与无上下文解析器相反?)可以做到这一点.另一个例子是C++语法上下文的任何部分都是敏感的吗?这个问题用"是......"回答.同样在这里:什么是模糊的上下文自由语法?
我不明白这个C++模糊性与上下文敏感性有什么关系.我不认为有任何上下文敏感的语法可以处理这种歧义.例如,如果你采用像Typedef,<other>*,PointerDeclaration - > Ident"*"Ident这样的虚构规则
那么你仍然无法确定(使用纯解析)在Typedef期间是否使用了具体的第一个Ident(例如"x")(例如typedef double x;).
因此,可能在链接的问题中使用术语"上下文敏感性",尽管意味着像上下文依赖一样简单(例如,需要比简单解析器提供的更多信息).或者"真实的"上下文敏感性"与歧义之间是否有任何联系.
编辑更多指定问题:在无上下文语法中是否存在任何可以通过使用上下文相关语法处理的歧义.这个问题发生在我身上,因为在链接的问题中,它听起来像C++模糊性有时被称为上下文敏感性问题.
Edit2附加信息:计算机系统在第346页上指出,上下文相关语法可以表示具有相同数量的实际和形式参数的要求.但这非常麻烦,因为你需要很多复杂的规则.但也许这也适用于前面提到的C++模糊性.所以我们有像这样的规则
"Typedef double x",<other>*,PointerDeclaration - >"x""*"Ident
当然,这些规则将非常有限,你需要大量的表达每种可能性.至少这可能是问题答案的一种方法,如果(理论上)无上下文的自由模糊可以用上下文敏感规则的使用来代替
今天我对这段代码片段的名称引用不明确这一事实感到震惊:
class A
{
private:
typedef int Type;
};
class B
{
public:
typedef int Type;
};
class D : A, B
{
Type value;//error: reference to 'Type' is ambiguous
};
Run Code Online (Sandbox Code Playgroud)
唔!假设您是 class 的作者,A并且您的 class 已经被不同的人和不同的项目随处使用。有一天你决定重写你的A类。这是否意味着您不能在不破坏他人代码的情况下在新类中使用任何新的(甚至私有的)名称?
这里的约定是什么?
我试图找到关于模板关键字的任何信息用作消除歧义,但没有任何相关信息.可能我正在搜索错误的关键字,但标准中没有.template或 - >模板.谷歌只显示来自不同论坛的GCC问题,但没有真正解释它用于什么.
第11行(在GCC上)没有模板关键字编译的代码无法编译,但我不太确定这是否符合标准.
template<typename B>
struct S1
{
template<typename T> void test() {}
};
template<typename T>
struct S2
{
S2()
{
S1<T>().template test<int>();
}
};
int main()
{
S2<int>();
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:为什么这里使用了模板关键字,没有那个关键字会有什么样的歧义?我在哪里可以阅读(我非常感谢链接到标准).
谢谢.
我不敢相信我以前从未遇到过这个,但为什么我的代码会出现编译器错误?
public class Main
{
public Main()
{
var ambiguous = new FooBar(1);
var isConfused = ambiguous.IsValid; // this call is ambiguous
}
}
public class FooBar
{
public int DefaultId { get; set; }
public FooBar(int defaultId)
{
DefaultId = defaultId;
}
public bool IsValid
{
get { return DefaultId == 0; }
}
public bool IsValid(int id)
{
return (id == 0);
}
}
Run Code Online (Sandbox Code Playgroud)
这是错误消息:
'FooBar.IsValid'和'FooBar.IsValid(int)'之间的歧义
为什么这个含糊不清?
我认为有两个原因不应该含糊不清:
IsConfused.IsConfused.歧义在哪里?
QString::arg()当字符串包含位置标记之后的数字时,会出现问题.从QString::arg()功能描述中不清楚在这种替换的情况下会发生什么:
QString("String for replacement %1234").arg("blah");
Run Code Online (Sandbox Code Playgroud)
这会导致"String for replacement blah234"或"String for replacement blah34"?
我查看了QT的源代码来回答这个问题.看起来寻找位置标记的算法似乎是"贪婪的",并且在上面的例子中它将采用两个数字.
以下是QString::arg()(QT 4.8.4)中使用的QT函数的来源:
static ArgEscapeData findArgEscapes(const QString &s)
{
const QChar *uc_begin = s.unicode();
const QChar *uc_end = uc_begin + s.length();
ArgEscapeData d;
d.min_escape = INT_MAX;
d.occurrences = 0;
d.escape_len = 0;
d.locale_occurrences = 0;
const QChar *c = uc_begin;
while (c != uc_end) {
while (c != uc_end && c->unicode() != '%')
++c;
if (c == uc_end)
break; …Run Code Online (Sandbox Code Playgroud) ambiguity ×10
c++ ×6
c# ×3
.net ×1
anonymous ×1
base ×1
delegates ×1
grammar ×1
inheritance ×1
method-call ×1
namespaces ×1
overloading ×1
private ×1
qstring ×1
qt ×1
scope ×1
templates ×1
types ×1