【问题标题】:C++ concepts lite and type alias declarationC++ 概念 lite 和类型别名声明
【发布时间】:2017-03-12 23:50:06
【问题描述】:

是否可以使用 typedefusing 在概念内声明类型别名,如概念 TS 所建议的那样? 如果我尝试类似以下 MWE,则代码无法编译(使用 gcc 6.2.1 和 -fconcepts 开关)

#include <type_traits>

template<typename T>
concept bool TestConcept ()
{
    return requires(T t)
    {
        using V = T;
        std::is_integral<V>::value;
    };
}

int main()
{
    return 0;
}

产生的错误:

main.cpp: In function ‘concept bool TestConcept()’:
main.cpp:8:9:  error: expected primary-expression before ‘using’  
         using V = T;  
         ^~~~~   
main.cpp:8:9: error: expected ‘}’ before ‘using’
main.cpp:8:9: error: expected ‘;’ before ‘using’
main.cpp:4:14: error: definition of concept ‘concept bool TestConcept()’ has multiple  statements
 concept bool TestConcept ()  
              ^~~~~~~~~~~ 
main.cpp: At global scope:
main.cpp:11:1: error: expected declaration before ‘}’ token
 } 
 ^

【问题讨论】:

  • 您似乎想使用typedef V T;,这会将T 别名为Vusing 用于调用命名空间或命名空间中的特定标识符。这是一个示例:stackoverflow.com/questions/10103453/…
  • @JamesMurphy 抱歉,但是从 c++11 开始,您可以使用 using 关键字来表达类型别名,就像您之前使用 typedef 所做的那样。这是参考:en.cppreference.com/w/cpp/language/type_alias.
  • @JamesMurphy 该示例也因 typedef 失败,基本上具有相同的错误消息。正如 erikzenker 所说,现在的语法应该是等价的。
  • 我没有使用足够多的 C++11 来了解这些细微差别,但我想我会去寻找有关该主题的东西。如果语法相同,请尝试改用typedef

标签: c++ typedef c++-concepts using-declaration


【解决方案1】:

没有。根据概念TS,要求是:

要求
简单的要求
类型要求
复合要求
嵌套要求

simple-requirement 是一个 表达式,后跟 ;type-requirement 类似于 typename T::inner。另外两个听起来就像名字所暗示的那样。

类型别名是一个声明,而不是一个表达式,因此不符合需求的要求。

【讨论】:

  • 这对我来说是不必要的限制。您是否知道是否存在合理的解决方法,而不是一遍又一遍地编写相同的复杂类型?
【解决方案2】:

这对我来说是不必要的限制。您是否知道是否存在合理的解决方法,而不是一遍又一遍地编写相同的复杂类型?

您可以将约束的实现推迟到另一个概念,将这些类型作为模板参数传递:

template<typename Cont, typename It, typename Value>
concept bool InsertableWith = requires(Cont cont, It it, Value value) {
    // use It and Value as much as necessary
    cont.insert(it, std::move(value));
};

template<typename Cont>
concept bool Insertable = requires {
    // optional
    typename Cont::const_iterator;
    typename Cont::value_type;
} && InsertableWith<Cont, typename Cont::const_iterator, typename Cont::value_type>;

如果您正在考虑这样做,我建议您在做出决定之前先尝试简单的示例。你如何编写你的概念和约束决定了编译器如何报告错误,当然,有好的错误是使概念有用的重要部分。让我的概念更容易编写,同时让错误更难理解,这不是我会掉以轻心的权衡。

例如,这就是我冗余添加typename Cont::const_iterator; 作为显式约束的原因。这使编译器有机会报告此类型要求。我在选择 InsertableWith 作为概念名称时也很小心:我本可以轻松地使用 detail::Insertable,但同时涉及 Insertabledetail::Insertable 的错误可能会因此更加令人困惑。

最后请注意,这一切都依赖于编译器的实现质量,所以我不希望任何方法暂时是确定的。我鼓励玩这个Coliru demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-20
    • 1970-01-01
    • 2011-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多