This question is in spirit a follow-on from this question from another user, which has some excellent answers: Is it possible to write a template to check for a function's existence?
I want to do exactly what is described in this question, except I want to be able to do it for a constructor. Eg, given these two types:
class NormalType
{
public:
NormalType()
{
std::cout << "NormalType::NormalType()" << std::endl;
}
};
class SpecialType
{
public:
SpecialType()
{
std::cout << "SpecialType::SpecialType()" << std::endl;
}
SpecialType(int someArg)
{
std::cout << "SpecialType::SpecialType(int someArg)" << std::endl;
}
};
And this helper function for constructing an object:
template<class T>
class ConstructHelper
{
public:
template<bool HasSpecialConstructor>
static T Construct()
{
return T();
}
template<>
static T Construct<true>()
{
return T(int(42));
}
};
I want to be able to write code like this:
NormalType normalType = ConstructHelper<NormalType>::Construct<has_special_constructor<NormalType>::value>();
SpecialType specialType = ConstructHelper<SpecialType>::Construct<has_special_constructor<SpecialType>::value>();
Where the desired results are that NormalType::NormalType()
is called, and SpecialType::SpecialType(int someArg)
is called. The missing ingredient here is that critical has_special_constructor
helper, which can determine if our special constructor exists for a given type.
The previous question I referenced deals with checking if a given function exists on a type, and there were a variety of working solutions presented. Unfortunately, most of them rely on being able to take the address of the target method, and as per the C++ spec, you can't take the address of a constructor (12.1.10). Of the remaining working solutions, all of them seem to rely on SFINAE with decltype on an arbitrary expression in a template specialization. That is a simple way to solve this problem, but unfortunately I'm working on Visual Studio 2013, which doesn't properly support the C++11 SFINAE rules, and still won't with the release of "Visual Studio 14" either. With proper SFINAE support, I should be able to do this for example:
template<class T>
struct has_special_constructor
{
template<class S>
struct calculate_value: std::false_type {};
template<>
struct calculate_value<decltype(T(int(42)))>: std::true_type {};
static const bool value = calculate_value<T>::value;
};
But that won't compile under VS2013 if I try and test a type that doesn't define my target constructor, due to the lack of SFINAE support. That said, I'm not yet convinced this is impossible, I think there might be a way to make it work, but I haven't been able to find a solution so far. Anyone out there see a way to do this that I've overlooked?
Here's some more info about what I'd need in order to accept an answer as a solution to this problem:
It must be possible to resolve
has_special_constructor<T>::value
for any given type without additional code being written for that specific type.I'm primarily targeting Visual Studio 2013, so any solution must work in that environment. I know a fully conforming C++11 compiler could manage this problem more easily, but I'm looking for something that can function now on my current target compiler.
If anyone can supply a solution that works in a C++03 compiler (IE, without any C++11 features) I'll accept that over one that uses C++11 features.
I'd settle for a MSVC extension-based workaround at this point, since I can use the preprocessor to fall back to this method until full C++11 support comes along.