是否存在绝对需要typedef的情况?

时间:2011-08-09 15:30:06

标签: c++ type-conversion typedef coercion safe-bool-idiom

请考虑以下摘录自safe bool idiom

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

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

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

8 个答案:

答案 0 :(得分:9)

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

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

具有identity的以下定义:

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

你可以说identity仍然使用typedef,但这个解决方案对我来说足够“好”。

答案 1 :(得分:3)

需要typedef的一个案例(与您的问题无关)是在使用

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

  

输入* va_arg(va_list ap, type );

...

  

参数 type 应为a   指定的类型名称,以指向对象的指针类型   只需通过后缀a *来获得指定的类型   

答案 2 :(得分:3)

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

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

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

答案 3 :(得分:2)

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

大多数STL代码都位于typedef之上,我们应该/必须使用它们!

答案 4 :(得分:2)

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

答案 5 :(得分:2)

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

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

我不是说它很漂亮......

答案 6 :(得分:1)

typedef不是宏,你的第二个例子不等同于第一个例子。在第一种情况下,您的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();
   }
};

答案 7 :(得分:1)

我刚用clang ++:

遇到了这个问题
foo.cpp:17:8: error: must use a typedef to declare a conversion to 'void (*(int))()'

并且有一个C ++ 11 STL模板,它涵盖了身份&lt; T&gt;功能性:

#include <type_traits>
…
struct foo {
     void bar( ) const { }
     operator std::common_type<void(foo::*)( )const>::type( ) { return &foo::bar; }
};