Delayed evaluation of template type function

Viewed 1255

I read "The C++ Programming language 4th edition, 1st printing, by Bjarne Stroustrup" book (from Amazon.com). Page 785. Stroustrup is explaining how he can eliminate explicit writing of "::type", when using "std::conditional + std::make_unsigned", using "type aliases" (keyword "using"). But that using "type aliases" on "std::conditional + std::make_unsigned" is causing compile errors. By now everything is as it should be. And he goes on to show how to elimintate these compile errors using "delayed evaluation of template type function".

The question is on the line Atype<make_unsigned<string> and myType2<string> ....

I used g++ 4.8.2.

Compile:

g++ -std=c++1y test45.cpp -o a

#include <type_traits>
#include <string>
#include <iostream>
#include <typeinfo>  // for typeid(...)
using namespace std;

template<class T>
struct ErrIndicator {
   typedef ErrIndicator<T> type;
};

template<bool C, class T, class F>
using Conditional = typename conditional<C,T,F>::type;

template<typename T>
using Make_unsigned = typename make_unsigned<T>::type;

template<template<typename ...> class F, typename... Args>
using Delay = F<Args ...>;

template<class T>
using myType1 = Conditional<is_integral<T>::value,
    Make_unsigned<T>,
    ErrIndicator<T>
    >;

template<class T> 
    using myType2 = Conditional<is_integral<T>::value,
    Delay<Make_unsigned, T>,   // delayed evaluation
    ErrIndicator<T>
    >;

template<class T>
    using myType4 = Conditional<is_integral<T>::value,
    make_unsigned<T>,
    ErrIndicator<T>
    >;

template<typename T>
class Atype {}; 

template<typename T>
void func1(T &ia /* output param */) {
  cout << "unsigned integral type" << endl;
  ia = 4;  // "unsigned integral type" computation
}

template<typename T>
void func1(ErrIndicator<T> &) {
  cout << "non integral type: " << typeid(T).name() << endl;
}

int main() {
  myType1<int> var1a; // OK
  // myType1<string> var1b; // Error; The book says error
  //                    // should occur here. Here I understand.
  myType2<int> var2a; // OK
  // myType2<string> var2b; // Error - why?. Maybe I didn't get it,
  //                      // but I understand the book as no
  //                      // error should occur here.
  //                      // @DyP answered it.
  Atype<make_unsigned<string> > var3;  // OK here, look below at @DyP
  //                             // for "foo, bar, X" why
  //                        // make_unsigned<string> is not an error here.
  // make_unsigned<string> var6; // Error
  // Atype<make_unsigned<string>::type > var4;  // Error
  Atype<make_unsigned<int>::type > var5;  // OK
  //-------------
  myType4<string>::type var7;    // Look below for "myType3", where @Yakk
  //                          // obviates the necessity to write "::type".
  // rsl7 = 1:
  cout << "rsl7 = " << is_same<decltype(var7), ErrIndicator<string> >::value << endl; 
  func1(var7);  // "non integral type" overload of func1()
  //---------
  myType4<int>::type var8;
  // rsl8 = 1:
  cout << "rsl8 = " << is_same<decltype(var8), unsigned int>::value << endl; 
  func1(var8);  // "unsigned integral type" overload of func1()
}
2 Answers
Related