2016-10-30 51 views
9

是否有可能使用typedefusing在概念内部声明类型别名,正如Concepts TS? 如果我尝试像下面MWE,代码不编译(用gcc 6.2.1和-fconcepts开关)C++概念lite和类型别名声明

#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 
} 
^ 
+0

看起来你想使用'typedef V T;',这会将'T'替换为'V'。 'using'用于调用命名空间的名称空间或特定标识符。下面是一个例子:http://stackoverflow.com/questions/10103453/is-typedef-inside-of-a-function-body-a-bad-programming-practice –

+1

@JamesMurphy对不起,但自从C++ 11你可以使用'using'关键字来表达类型别名,就像你之前用'typedef'所做的那样。以下是参考资料:http://en.cppreference.com/w/cpp/language/type_alias。 – erikzenker

+0

@JamesMurphy该示例也失败了typedef,基本上具有相同的错误消息。正如erikzenker所说,现在的语法应该是相同的。 – Slizzered

回答

2

号根据概念TS ,一个要求是:

requirement:
    simple-requirement
    type-requirement
    compound-requirement
    nested-requirement

简单的要求快递离子其次是;类型要求类似于typename T::inner。另外两个听起来像名字所暗示的。

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

+0

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

2

This feels unnecessarily restrictive to me. Do you know if there exists a reasonable workaround instead of writing the same complicated type over and over again?

您可以推迟的约束到另一个概念的实施,通过这些类型作为模板参数:

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