首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++11:在无效表达式上使用decltype

C++11:在无效表达式上使用decltype
EN

Stack Overflow用户
提问于 2013-06-14 22:57:55
回答 1查看 442关注 0票数 0

假设我有一个struct (在现实生活中,这是一个自动机):

代码语言:javascript
复制
struct automaton
{
  bool get_final() const { return final; }
  void set_final()       { final = true; }
  bool final = false;
};

为此,我想提供一个视图,可以看到它被转置(低,反转,或镜像)。因为我不只有一个automaton类,所以我有一个类模板,它包装了我的自动机(我真的想要组合,而不是继承),并将所有函数调用反弹到包装的自动机,颠倒需要的东西。为了简单起见,在这里,它只转发调用。

用手,我会得到

代码语言:javascript
复制
template <typename Aut>
struct transposed_by_hand
{
  Aut& aut;
  auto get_final() const -> bool
  {
    return aut.get_final();
  }

  auto set_final() -> void
  { 
    aut.set_final(); 
  }
};

但是有很多函数,我不想在包装器中硬编码这么多信息(函数签名)。多亏了不同的模板和对传入参数的完美转发,以及对结果的decltype,很容易有一个宏来定义所有常量成员函数,而另一个宏来定义非常数成员函数(不同之处就是const)。基本上,在这种情况下,它可以归结为:

代码语言:javascript
复制
template <typename Aut>
struct transposed_with_decltype
{
  Aut& aut;
  auto get_final() const -> decltype(aut.get_final())
  {
    return aut.get_final();
  }

  auto set_final() -> decltype(aut.set_final())
  {
    aut.set_final(); 
  }
};

这对于非常量自动机很有效,但是如果我包装一个常量自动机就会崩溃:

代码语言:javascript
复制
int main()
{
  const automaton aut;
  transposed_by_hand<const automaton> trh = { aut };
  transposed_with_decltype<const automaton> trd = { aut };
}

我的编译器抱怨(G++ 4.9):

代码语言:javascript
复制
f.cc: In instantiation of 'struct transposed_with_decltype<const automaton>':
f.cc:44:49:   required from here
f.cc:34:12: error: passing 'const automaton' as 'this' argument of 'void automaton::set_final()' discards qualifiers [-fpermissive]
       auto set_final() -> decltype(aut.set_final())
            ^

和(Clang++ 3.3):

代码语言:javascript
复制
f.cc:42:23: error: default initialization of an object of const type 'const automaton' requires a user-provided default constructor
      const automaton aut;
                      ^
f.cc:34:36: error: member function 'set_final' not viable: 'this' argument has type 'const automaton', but function is not marked const
      auto set_final() -> decltype(aut.set_final())
                                   ^~~
f.cc:44:49: note: in instantiation of template class 'transposed_with_decltype<const automaton>' requested here
      transposed_with_decltype<const automaton> trd = { aut };
                                                ^
f.cc:6:12: note: 'set_final' declared here
      void set_final()       { final = true; }
           ^
2 errors generated.

他们是对的!decltype中的表达式打破了包装自动机的不变性。但是,我发誓,我不会使用这个函数。就像我不会使用相应的手工包装一样。

所以我的问题是:有没有一种方法可以编写包装set_final的定义,这样我就不必拼写出它的签名(输入和输出)?我尝试过使用std::enable_if,但它并没有改变这里的问题。

代码语言:javascript
复制
template <typename Aut>
struct transposed_with_decltype
{
  Aut& aut;
  auto get_final() const -> decltype(aut.get_final())
  {
    return aut.get_final();
  }

  auto set_final() -> typename std::enable_if<!std::is_const<Aut>::value,
                                              decltype(aut.set_final())>::type
  {
    aut.set_final(); 
  }
};

提前谢谢。

EN

回答 1

Stack Overflow用户

发布于 2013-06-15 03:41:42

我可以通过使用Xeo在他的评论中提到的建议来让它工作(使用GCC 4.6)。也就是说,我将该函数转换为一个简单的模板,如下所示:

代码语言:javascript
复制
template<typename = void>
auto set_final() -> decltype(aut.set_final())  {
    return aut.set_final(); 
}

==编辑==

Luc Danton在下面评论说,最近的GCC可能会拒绝代码,抱怨decltype不依赖。我这里只有4.6,但也许可以使用下面这样的东西来解决这个问题:

代码语言:javascript
复制
template<typename KLUDGE = int>
auto set_final() -> decltype((&aut+KLUDGE(0))->set_final())  {
    return aut.set_final(); 
}

YMMV.

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17111406

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档