Home > Blockchain >  SFINAE in C 98
SFINAE in C 98

Time:10-20

I am trying to understand how does SFINAE work in C 98.
My aim is to write a simple template function that would only be called when an integer is passed. But the plan is to do it without specializing a function for typename T = int, but definining a template function with a dummy parameter that checks wether the pased element is an integer. Heres my toy code :

// header.h

#include <iostream>
#include <cstddef>

struct false_type {
    static const bool value = false;
};

struct true_type {
    static const bool value = true;
};

template < bool, typename T >
struct enable_if
{};

template <typename T>
struct enable_if<true, T>
{ typedef T type; };

template <typename T>
struct is_integral : false_type {};

template <>
struct is_integral<int> : true_type {};

/* ... more is_integral specializations ... */

template < typename T > 
void print(T& value, typename enable_if<!is_integral<T>::value,T>::type* = 0)
{
    std::cout << "FIRST " << value << std::endl;
}

template < typename T > 
void print(T& value)
{
    std::cout << "SECOND " << value << std::endl;
    std::cout << std::boolalpha;
    std::cout << is_integral<T>::value << std::endl;
}

// main.cpp

#include "header.hpp"

int main() {
    int a = 123;
    print<int>(a);
}

It is compiled as follows : g -Wall -Wextra -Werror -std=c 98 -pedantic -g3 -Wno-c 0x-compat main.cpp .
I took the enable_if syntax from this question's first answer, which needed for an implementation of enable_if and is_integral to be carried out in C 98 (<type_traits> is not a C 98 header).
My problem is that this program outputs:

SECOND 123
true

My question is, why does this happen? I expected the first implementation of print to be called. Is my approach impossible (i.e. this can only be done by specializing a generic print function to int), or am I doing something wrong ?

CodePudding user response:

My aim is to write a simple template function that would only be called when an integer is passed.

There is no need to provide 2 overloads. You can just remove the ! and have the first primary template as shown below:

template < typename T > 
void print(T& value, typename enable_if<is_integral<T>::value,T>::type* = 0)
{
    std::cout << "FIRST " << value << std::endl;
}

int main() {
    int a = 123;
    print<int>(a);  //works 
    //print<double>(4.4);                      //doesn't work
    //print<std::string>(std::string("f"));   //doesn't work
    //print(3.3);                             //doesn't work
    double d = 3.3;
    //print(d);                               //doesn't work
}
  • Related