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()
}
make_unsigned
requires its template argument to be of integral, but notbool
type. As I understand it, it doesn't care that you don't use the nestedtype
. – dypDelay
is doing? And what quote from the book makes you think that? I mean, delayed evaluation could help, but what makes you thinkDelay
does that? – Yakk - Adam NevraumontMake_unsigned
until it has been checked that the type is integral. – dypconditional< is_integral<T>::value, make_unsigned<T>, Error<T> >::type
and talks about that using this instead oftypename make_unsigned<T>::type
would prevent a compile-time error. – dyp