- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我遇到了一些用 VS7.1 编写的代码,现在我正试图让它在 MacOSX 上工作。我理解的下面的代码片段关于SFINAE原则。据我了解,代码用于在编译时通过依赖一些模板实例化魔法来知道什么类型。简而言之,通过查看模板参数来选择正确的重载。
这是我的代码。稍微简化以仅显示问题。
template <typename T>
struct SomeClass
{
};
template <>
struct SomeClass<char>
{
typedef char Type;
};
template <typename T>
struct IsChar
{
typedef char Yes;
typedef int No;
template <typename U>
static Yes Select(U*, typename SomeClass<U>::Type* p = 0);
template <typename U>
static No Select(U*, ...);
static T* MakeT();
const static bool Value = sizeof(Select(MakeT())) == sizeof(Yes);
};
我只是像这样使用它:
if (IsChar<int>::Value)
{
...
编译时上面的代码运行良好,并且由于使用 int 时缺少 Type 的 typedef,它会选择最顶层的类。
如果我现在改用 char...
if (IsChar<char>::Value)
{
...
...编译器会提示不明确的 Select 函数,因为它不知道要使用哪一个。从我读过的内容来看,重载决议对省略号参数 (...) 的优先级最低。因此,它应该知道选择第一个。
代码至少在 VS7.1 上运行良好,但在 MacOSX 的 gcc 和 Linux 的 gcc4.4 上不行。
有什么建议可以纠正这个问题吗?也许它通常以另一种方式完成?
谢谢!
更新:我意识到我提供的示例代码可能稍微过于简化了,因为我相信我们并没有在这里检查类型,即使我错误地让它看起来像那样。今晚我必须为您收集更多信息,因为我这里没有代码。对此感到抱歉。
UPDATE2:即使我的演讲很糟糕,这是因为不熟悉原始代码或以这种方式使用模板。与此同时,我挖掘了更多信息,假设这些结构出于某种原因存在 X 并且我给出的名称都是错误的,那么编译器问题呢?为什么不能在这里选择正确的重载函数?这也是我感兴趣的。正如我所说,我会更好地解释总体目标是什么。
编辑
仔细查看原始代码后,它使用了 boost::integral_constant 和 boost::enable_if,就像这里建议的那样。问题是特定于如何推导模板参数并且它没有按照设置的方式工作。但是,按照乔治在他的回答末尾提出的建议,我可以纠正事情以接受事情。我现在有以下内容:
typedef char Yes;
typedef int No;
template <typename U> static Yes Select(typename SomeClass<U>::Type* p);
template <typename U> static No Select(...);
static const bool Value = sizeof(Select<T>(0)) == sizeof(Yes);
这很好用。在进行一些试验时,我发现在 Select 函数中有两个函数参数会导致问题。我还没找到原因。当我更好地理解事情时,我会回到这个问题上。
感谢您的帮助。至少我现在明白这里的原则以及事情应该如何运作。只有一些细节,目前还不得而知。
最佳答案
除非我误解了意图,否则上述用法示例不需要使用 SFINAE。如果你只想静态断言 Type
的类型,你可以使用这样的东西:
template<class T1, class T2> struct SameType {
static const bool Value = false;
};
template<class T> struct SameType<T, T> {
static const bool Value = true;
};
template <typename T>
struct IsChar {
static const bool Value = SameType<T, char>::Value;
};
如果你真的需要将它用于 SFINAE(即基于模板参数禁用/启用功能),只需将上面的内容与类似 Boosts enable_if
的内容结合使用:
template<class T>
typename boost::enable_if_c<IsChar<T>::Value, void>::type
someFunction() {
}
或者如果你可以一路提升:
template<class T>
typename boost::enable_if<boost::mpl::is_same<T, char>, void>::type
someFunction() {
}
更新:
重读这篇文章,如果你真的想检查 SomeClass
的特化是否有 typedef Type
,你应该能够使用来自 over here 的解决方案:
template<class T> struct HasType {
template<class U> static char (&test(typename U::Type const*))[1];
template<class U> static char (&test(...))[2];
static const bool Value = (sizeof(test< SomeClass<T> >(0)) == 1);
};
在那种情况下,IsChar
肯定是用词不当,HasType
或 HasTypedefType
之类的名称会更具描述性:)
关于c++ - 使用 SFINAE 原理时重载函数有歧义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4872474/
虽然我正在运行以测试此 thread 中的一些代码我发现了一件奇怪的事情,如果你考虑下面的程序 import java.util.ArrayList; import java.util.List; p
我只是很好奇为什么使用 using 指令以这种方式设计它。对于 1) struct 被视为命名空间,对于 2) 它不是: struct foo { using type0 = int; }; na
我需要在 ANTLR 中匹配一条消息,该消息包含由/分隔的 2 个字段第一个字段可以有 1..3 数字,第二个字段可以有 1..2 数字, 这不起作用 msg: f1 '/' f2; f1: DIGI
我想定义一个带有 x, y, z 坐标的 3D 矢量。可以使用(+)运算符添加向量,并可以使用length函数计算长度 如果我想编译它,我会收到以下错误: It could refer to eith
所以,今天我一直在测试 Java 的重载技术,但遇到了我无法解释的歧义。基本上,当存在带有原语及其相应包装器的可变参数方法时,编译器会提示并且无法决定选择哪一个,我不明白为什么?人类很容易决定而不是编
发现: Ambiguity while overloading the cast operator 和 C++ Operator Ambiguity 没有帮助 情况: 在容器类的内部我有: opera
我正在使用以下 XPath 片段 ancestor::contribution[1]/preceding-sibling::contribution[@speaker-reference][1] 我的
在尝试依赖可变参数模板实现一些事情时,我偶然发现了一些我无法解释的事情。我将问题归结为以下代码片段: template struct A {}; template class Z, typenam
我最近对 LALR 的研究足以写一篇 LALR generator ,并且我正在尝试为其构造一个 java 或 c# 风格的语法(其开头指定为 here )。 我知道编写解析器生成器需要额外的努力
在阅读 wikipedia article关于修订控制的文章,我发现了一些似乎定义不明确的术语,并且想知道它们是如何在现实世界中实际使用/应用的。具体来说: “主线”与“基线” “分支”与“流” “结
我有以下代码: class A{ public void print(A a){ System.out.println("A 1"); } } class B exte
考虑我试过的以下查询,有两个表,Orders 和 Customers,每个表都有列名称 CustomerID,当我尝试显示两个 CustomerID 时,只有一列显示,我不明白为什么会这样,或者我是理
我正在为基本汇编语言编写一个简单的组合词法分析器/解析器。我的问题是,在解析操作码时,我需要解析一些十六进制,它是指令计数器,可能是立即值等,以及实际的操作码。 基本上,当解析像 add 这样的东西时
我正在尝试在 mysql 中跨两个不同的数据库进行标题搜索,以匹配来自不同来源的数据。在 db1 或 db2 中,标题有时会在一个数据库中以“第一个标题”开头,而在另一个数据库中则以“第一个标题”开头
我对 token 级别的歧义有疑问。 问题看起来是这样的。我的代码看起来像这样,因此标记 t_UN1 具有更高的优先级。 t_ignore = ' \t\v\r' # whitespace ....
在 Main() 的最后一行,我在尝试执行指针操作时遇到错误,但我实际上想做的是调用我在 Foo 类中定义的乘法运算符。如果这不是调用乘法的语法,那是什么? namespace test {
在此page它说: The "00" specifier causes the value to be rounded to the nearest digit preceding the decim
我正在使用 C++ Builder 并使用 TDateTime 数据类型创建 GUI 应用程序。 当我在 TDateTime 对象上使用 MonthOf() 方法时,我得到的值比 TDateTime
$7.3.3/14 (C++03) struct A { int x(); }; struct B : A { }; struct C : A { using A::x; int x(in
我一直在开发一种适配器类,当我在 clang 下遇到问题。当定义了左值引用和右值引用的转换运算符时,您会在尝试从您的类中移出时遇到歧义编译错误(当这样的代码应该没问题时,如 operator cons
我是一名优秀的程序员,十分优秀!