【问题标题】:How to refer current class using decltype in C++11?如何在 C++11 中使用 decltype 引用当前类?
【发布时间】:2013-11-25 21:24:44
【问题描述】:

当我声明一个类静态方法时,是否可以使用decltype(或任何其他类似样式)引用当前类?例如,

class
AAA
{
    static AAA const make();
};

我正在尝试制作这样的东西。

class
AAA
{
    static decltype(*this) const make();  // Not working because there's no `this`.
};

*this 用于描述我想做什么。我想知道一些decltype() 可以解析为AAA 的表达式。

如果可能的话,我该怎么做?

【问题讨论】:

  • 我不知道你为什么要把static AAA const make()的简洁明了的形式换成间接的static decltype(*this) const make()。可读性是王道,明确你的类型对你的读者有很大帮助。
  • 这背后的想法是以特定的“智能”方式将make 函数添加到整个类层次结构中吗?这就是奇怪重复出现的模板参数模式的情况。如果这仅适用于一个类,我不明白需要派生返回类型,AAA 会很好(但是,我也不明白调用构造函数有什么问题)。
  • 我没有特定的用例实例。我突然对这个很好奇,如果可以的话,我想也许我以后可以想出一些有趣的应用程序。在这个问题中,我不主张任何想法的坏处。我也觉得这没什么用,但是这个问题困扰了我很长时间,所以我决定问这个。

标签: c++ c++11 static-methods decltype


【解决方案1】:

在 C++1y 中你可以这样做:

class
AAA
{
public:
    static auto make()
    {
        return AAA();
    }
};

int main()
{
    AAA aaa = AAA::make();
}

这在 C++11 中是不合法的,因为您需要为 make() 指定返回类型。在 C++98/03/11 中,您可以:

class
AAA
{
public:
    typedef AAA Self;

    static Self make()
    {
        return AAA();
    }
};

技术含量低,但可读性强。

<aside>

您应该避免按值返回 const 限定类型。这抑制了有效的移动语义。如果您想避免分配给右值,请创建一个以& 限定的赋值运算符。

</aside>

【讨论】:

    【解决方案2】:

    你也许可以这样做:

    #include<iostream>
    
    class AAA
    {
       int _i;
    
       public:
       AAA(int i): _i(i) {}
    
       static auto make(int i) -> typename std::remove_reference<decltype(*this)>::type
       {
          return {i};
       }
    
       void print()
       {
          std::cout << _i << std::endl;
       }
    };
    
    int main()
    {
        AAA aaa = AAA::make(1);
        aaa.print();
        return 0;
    }
    

    它至少在 GCC 4.7.2 上编译:)


    编辑 26/11-13:上面的代码不是合法的 c++,即使它用 gcc 编译,它也不用 clang 或 icpc。我很抱歉。

    【讨论】:

    • 用户 hvd 已经提出了类似的建议(现已删除),但不允许:[expr.prim.general]/3 关于表达式this:“它不应出现在可选的cv-qualifier-seq 并且它不应出现在静态成员函数的声明中”
    • @DyP:我怀疑可能是这种情况。谢谢,帖子已更新。
    【解决方案3】:

    刚刚发明了一种使用成员指针的方法,它似乎有效: https://godbolt.org/z/v-g5z0

    
        #define self_test(name) \
        void dummy__##name(void) {} \
        template  static T type__##name( void (T::*func)(void) ) { return T(); } \
        typedef decltype(type__##name(&dummy__##name)) self__##name; \
        static void test( void ) { self__##name::print(); }
    
        struct T1 {
          self_test(X);
          static void print() { printf( "this is T1\n" ); }
        };
    
        struct T2 {
          self_test(X);
          static void print() { printf( "this is T2\n" ); }
        };
    
        int main() {
          T1::test();
          T2::test();
        }
    

    这也不完美,它需要 -fpermissive 才能使用 gcc 编译, 但至少 gcc/VS/Intel 都编译它并且它可以工作。 实际上 gcc/mingw 甚至不需要 -fpermissive 。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-20
      • 1970-01-01
      相关资源
      最近更新 更多