36

考虑以下安全布尔成语的摘录:

typedef void (Testable::*bool_type)() const;
operator bool_type() const;

是否可以在没有 typedef 的情况下声明转换函数?以下不编译:

operator (void (Testable::*)() const)() const;
4

8 回答 8

9

啊,我只记得identity元函数。可以写

operator typename identity<void (Testable::*)() const>::type() const;

具有以下定义identity

template <typename T>
struct identity
{
    typedef T type;
};

您可能会争辩说它identity仍然使用 a typedef,但是这个解决方案对我来说已经足够“好”了。

于 2011-08-09T17:03:31.660 回答
3

需要a 的一种情况(与您的问题无关)typedef是使用

va_arg()宏。引用 C99 标准(7.15.1.1):

类型* va_arg(va_list ap,类型);

...

参数类型应该是一个指定的类型名称,这样指向具有指定类型的对象的指针的类型可以简单地通过后缀 * 来获得 类型

于 2011-08-09T16:16:34.600 回答
3

回答“是否存在绝对需要 typedef 的情况?” 从问题标题中,这是需要 typedef 的一个示例:

f(unsigned char());   // compiler error!
typedef unsigned char Byte;
f(Byte());            // fine!

在此处查看结果:http: //ideone.com/JPUra

于 2011-08-09T16:20:49.863 回答
2

我的分析表明,不使用typedef. 编译器将(其视为第一个标记并假设您正在重载() operator,它不应该有任何参数(参数将出现在下一组括号中)。放置任何一组额外的括号也无济于事 - 但实际上会混淆编译器并因此产生更多错误。

大多数 STL 代码都在初始化之上typedef,我们应该/必须使用它们!

于 2011-08-09T15:47:52.687 回答
2

在您的情况下,语法似乎要求使用 typedef 。转换函数 ID的格式必须为operator conversion-type-id转换类型 ID不能包含括号。因此,在转换为指向函数类型或指向成员函数类型时,必须使用 typedef。

于 2011-08-09T16:37:15.750 回答
2

在 C++11 中,您可以这样做(gcc 4.5.2):

operator decltype((void (Testable::*)() const)(0))() const ;

我不是说它漂亮...

于 2011-08-09T16:53:49.403 回答
1

Atypedef不是宏您的第二个示例不等于第一个示例。在第一种情况下,您typedef要定义一个仿函数,然后在仿函数类型的强制转换运算符中使用该类型。在第二个中,运算符使用了错误的语法,因为没有类型,所以没有指定运算符。我不知道怎么写,但通常有一种方法。

除了在 TMP 中制作人类可读的代码之外,Typedef 并不是真正必要的,即便如此,它也取决于你是什么样的人。

由于我无法提出替代语法,因此在某些情况下可能需要 typedef。我只是想到了另一个可能。假设您有一个带有特化的模板,其中包含一个返回类型如下的静态方法:

template <typename T>
struct WhateverHandler
{
   typedef T rType;
   static rType Whatever() { return rType(); }
};

template <>
struct WhateverHandler<std::string>
{
   typedef std::string rType;
   static rType Whatever() { return rType(); }
};

我认为在这种情况下,您也需要 typedef 来调用静态方法,而不管专业化如何,否则该方法可能会使编译器感到困惑,因为返回类型会有所不同,但它不会是适当的重载。

template <typename T>
struct WhateverUser
{
   typename WhateverHandler<T>::rType DoWhatever()
   {
       return WhateverHandler<T>::template Whatever();
   }
};
于 2011-08-09T15:51:18.317 回答
1

我刚刚用clang ++遇到了这个问题:

foo.cpp:17:8: error: must use a typedef to declare a conversion to 'void (*(int))()'

并且有一个 C++11 STL 模板,它涵盖了 identity<T> 功能:

#include <type_traits>
…
struct foo {
     void bar( ) const { }
     operator std::common_type<void(foo::*)( )const>::type( ) { return &foo::bar; }
};
于 2014-03-07T23:06:44.987 回答