Tuesday 15 January 2013

c++ - How to use std::enable_if with a condition which itself depends on another condition? -


I have a situation where I need to differentiate between two overloads, say, foo , std :: enable_if . The condition given to std :: enable_if is automatically dependent on the dependent type of the template parameter of foo .

What is the best way to express it using std :: enable_if ?

The following is the test code that I have done so far. I know that in addition to std :: enable_if , there are probably better ways to achieve what I want in the test code. However, the following is a simplified version of my use case, which requires itself std :: enable_if .

  #include & lt; Type_traits & gt; # Include & lt; Cassert & gt; Struct bar {baz = int; }; Template & lt; Class T & gt; Struct is_bar: std :: false_type {}; The template's & lt; & Gt; Straight is_bar & lt; Bars & gt; : Std :: true_type {}; Template & lt; Class bar & gt; Struct baz_type {typing = type name bar :: Falcon; }; Template & lt; Class T & gt; Typename std :: enable_if & lt; Std :: is_integral & lt; Typename baz_type & lt; T & gt; :: type & gt; :: Price, Difference & gt; :: type foo (t x) {return 7; } Template & lt; Square T & gt; Typename std :: enable_if & lt; ! Is_bar & lt; T & gt; :: value, int & gt; :: Type Fu (T x) {return 13; } Int main () {emphasis (foo (bar)) == 7); Emphasis (af (0) == 13); Return 0; }  

Compiler output:

  $ g ++ --version; Echo; G ++ -std = c ++ 11 repro.cpp g ++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 Copyright (C) 2013 Free Software Foundation, Inc. It's free software; See the source of copying conditions, there is no warranty; Not even for business or fitness for a particular purpose. Repro.cpp: 'struct baz_type & lt; Int & gt; In urgent: repro.cpp: 29: 3: 'template & lt; Class T & gt; Typename std :: enable_if & lt; Std :: is_integral & lt; Typename baz_type & lt; Bars & gt; :: type & gt; :: Price, et & gt; Required from type foo (T) [t = int] [repro.cpp: 49: 3] repro.cpp: 18: 33: error: 'int' is not a class, structure, or union type type Type = Typename bar :: baz;   

This code does not compile because the first charge of enable_if is used in foo depending on the nested type T Is:: baz . Because int is not of this nested type, the code is illegal.

What is the correct way to express what I have to express?

When I wrote down on Colluery, @Op has already shown the important part in its comments What works and what is, IMHO, is quite readable:

  template & lt; Class T, typename = typename std :: enable_if & lt; Is_bar & lt; T & gt; :: value & gt; :: type, typename = typename std :: enable_if & lt; Std :: is_integral & lt; Typename baz_type & lt; T & gt; :: type & gt; :: Price & gt; : Type & gt; Int Fu (T x) {return 7; } Template & lt; Class t, typename = typename name std :: enable_if & lt ;! Is_bar & lt; T & gt; :: value & gt; :: type & gt; Int Fu (T x) {return 13; }  

With C ++, one can also make it even smaller by using std :: enable_if_t .


No comments:

Post a Comment