2017-07-03 14 views
5

まだコンセプトライトTSが標準に統合されていないことを知りたいと思っています。私は、コンセプト体における論理和を短絡させる行動について混乱している。ここC++ Concepts Lite:コンセプト本体の短絡

が小さい例である:GCC 7.1と-fconceptsしてコンパイル

#include <type_traits> 
#include <iostream> 

template <typename T, typename ... Ts> concept bool myconcept = 
(sizeof...(Ts) == 0) || (std::is_same_v<T, std::common_type_t<Ts...>>); 

template <typename ... Ts> 
void myfunc(Ts ... args) requires myconcept<int, Ts...> { 
    (... , (std::cout << args << std::endl)); 
} 

int main() { 
    myfunc(); 
    return 0; 
} 

、エラーを与える:この例では

error: cannot call function 'void myfunc(Ts ...) requires myconcept<int, Ts ...> [with Ts = {}]' 

構造体std::common_type<Ts...>がないので、std::common_type_t<Ts...>が存在しませんTs = {}の場合、メンバーはtypeです。しかし、私はconcepts and constraintsにcppereference.comのマニュアルがsizeof...(Ts) == 0が満たされる

Disjunctions are evaluated left to right and short-circuited (if the left constraint is satisfied, template argument deduction into the right constraint is not attempted).

ので、テンプレート引数控除は、第2の制約で試行されてはならないとの要件myconcept<int, Ts...>が満たさなければならないことを述べているので、これはコンパイルすべきだと思います。

不思議なこと、プログラムをコンパイルする原因と宣言子の機能に直接要件を置く:

#include <type_traits> 
#include <iostream> 

template <typename ... Ts> 
void myfunc(Ts ... args) requires (sizeof...(Ts) == 0) || (std::is_same_v<int, std::common_type_t<Ts...>>) { 
    (... , (std::cout << args << std::endl)); 
} 

int main() { 
    myfunc(); 
    return 0; 
} 

は、この動作のための良好な説明がありますか?おかげさまで

+0

を「まだ標準にマージされる概念LiteのTSは、」私は、この情報を見つけることができますか?私の最後の情報は受け入れられなかった... – Klaus

答えて

2

cppreferenceに表示される熟達者の説明は正しいです。 n4674 draftから文言を選択し、同様非常に明確である:

A conjunction is a constraint taking two operands. A conjunction of constraints is satisfied if and only if both operands are satisfied. The satisfaction of a conjunction’s operands are evaluated left-to-right; if the left operand is not satisfied, template arguments are not substituted into the right operand, and the constraint is not satisfied. […]

(。§2[temp.constr.op] 17.10.1.1論理演算から)正確に我々は概念から行く方法を確立する文言のすべて以来と原子の束縛の結合または分離へのテンプレートはかなり長く、我々は素人の説明に固執するでしょう。

この記事の執筆時点では、概念のGCC実装は非常に実験的です。回避策としては、独自のコンセプトに問題のある部分をリファクタリングすることができます

template<typename T, typename... Ts> 
concept bool refactored = std::is_same_v<T, std::common_type_t<Ts...>>; 

template<typename T, typename... Ts> 
concept bool myconcept = sizeof...(Ts) == 0 || refactored<T, Ts...>; 

Coliru demo