T
trbabb
I've come across a bizarre case where the member type of enable_if seems tocontrol whether a partial specialization is found. If I pass any type other than the default of `void`, the specialization is hidden. I would not expect this type to matter at all, since in this case its only purpose is to trigger or disable SFINAE; the template parameter it fills is otherwise unused.
Consider this fairly simple case:
//============ specialize.cpp ============//
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <iostream>
using namespace boost;
using namespace std;
/***************************
* specialized type = void *
***************************/
template <typename T, typename Enable=void>
struct IsSpecialized {
static const bool specialized = false;
};
template <typename T>
struct IsSpecialized <T, typename enable_if<is_integral<T> >::type> {
static const bool specialized = true;
};
/***************************
* specialized type = int *
***************************/
template <typename T, typename Enable=void>
struct IsSpecializedInt {
static const bool specialized = false;
};
// note the `int` below:
template <typename T>
struct IsSpecializedInt <T, typename enable_if<is_integral<T>, int>::type> {
static const bool specialized = true;
};
/***************************
* main *
***************************/
int main(int argc, char **argv) {
cout << "specialized? (enable_if<...>::type = void): ";
cout << IsSpecialized<int>::specialized << endl;
cout << "specialized? (enable_if<...>::type = int): ";
cout << IsSpecializedInt<int>::specialized << endl;
return 0;
}
//============ end specialize.cpp ============//
The output:
It does not seem to matter whether I pass `int` or any other type to enable_if; only `void` seems to give the expected behavior.
The example above is scarcely modified from the example in the boost library documentation on enable_if for partial specializations.
I am using gcc, and this manifests with every release I have tried (including the current 4.8.1).
I cannot fathom a ruleset in which this makes sense. Is behavior in keepingwith the standard? If so, why does this happen? What is magical about `void` in the context of template resolution?
-tb
Consider this fairly simple case:
//============ specialize.cpp ============//
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <iostream>
using namespace boost;
using namespace std;
/***************************
* specialized type = void *
***************************/
template <typename T, typename Enable=void>
struct IsSpecialized {
static const bool specialized = false;
};
template <typename T>
struct IsSpecialized <T, typename enable_if<is_integral<T> >::type> {
static const bool specialized = true;
};
/***************************
* specialized type = int *
***************************/
template <typename T, typename Enable=void>
struct IsSpecializedInt {
static const bool specialized = false;
};
// note the `int` below:
template <typename T>
struct IsSpecializedInt <T, typename enable_if<is_integral<T>, int>::type> {
static const bool specialized = true;
};
/***************************
* main *
***************************/
int main(int argc, char **argv) {
cout << "specialized? (enable_if<...>::type = void): ";
cout << IsSpecialized<int>::specialized << endl;
cout << "specialized? (enable_if<...>::type = int): ";
cout << IsSpecializedInt<int>::specialized << endl;
return 0;
}
//============ end specialize.cpp ============//
The output:
specialized? (enable_if<...>::type = void): 1
specialized? (enable_if<...>::type = int): 0
It does not seem to matter whether I pass `int` or any other type to enable_if; only `void` seems to give the expected behavior.
The example above is scarcely modified from the example in the boost library documentation on enable_if for partial specializations.
I am using gcc, and this manifests with every release I have tried (including the current 4.8.1).
I cannot fathom a ruleset in which this makes sense. Is behavior in keepingwith the standard? If so, why does this happen? What is magical about `void` in the context of template resolution?
-tb