|
Boost Users : |
From: Angus Leeming (angus.leeming_at_[hidden])
Date: 2005-04-05 10:31:15
David Abrahams wrote:
> Angus Leeming <angus.leeming_at_[hidden]> writes:
>
>> Is it possible to use enable_if with a constructor?
>
> In principle, yes. You just add a dummy default parameter for the
> enabler.
>
>> For example, I'd like to define a constructor that allows only
>> certain values of an enum:
>
> No chance; that's a runtime test... or you'd have to specify the enum
> as a template argument to the ctor explicitly... but you can't provide
> explicit template arguments to ctors.
Many, many thanks, Dave, both for the explanations and for the working
code.
Your code worked perfectly of course, but I decided to use a static "set"
member function to return a foo instance:
foo x(foo::set<foo::state2>());
I guess that this is semantically equivalent to your
foo x(mpl::int_<foo::state2>());
FWIW, I include my working version of this MPL code at the bottom of this
mail. However, it all seems like a lot of machinery. In my case, there are
only a few "valid" enum values. What are the advantages of the Boost.MPL
approach over the functionally identical:
#include <iostream>
class foo {
public:
enum state {
state1,
state2,
state3
};
// Only the specializations (below) of this template will compile.
template <int N>
static foo
set() { return invalid_value; }
private:
foo(state)
{
std::cout << "foo" << std::endl;
}
};
template <>
foo foo::set<foo::state2>() { return foo::state2; }
template <>
foo foo::set<foo::state3>() { return foo::state3; }
int main()
{
// Compiles, as expected.
foo f1 = foo::set<foo::state2>();
foo f2(foo::set<foo::state2>());
// Fail to compile, as expected.
// foo f3 = foo::set<foo::state1>();
// foo f4(foo::set<foo::state1>());
return 0;
}
Regards,
Angus
-----------------------------------------------------------------------
My version of Dave Abrahams's working version of my broken original ;-)
#include <boost/type_traits/is_integral.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/assert.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/end.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/lambda.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/vector_c.hpp>
#include <iostream>
namespace boost {
namespace mpl {
template <class S, int N>
struct contains_c
: not_<
is_same<
typename find_if<S,
equal_to<_1,
integral_c<typename S::value_type, N>
>
>::type
, typename end<S>::type
>
>
{};
} // namespace boost
} // namespace mpl
class foo {
public:
enum state {
state1,
state2,
state3
};
// Will compile only for state2 and state3
template <int N>
static
typename boost::enable_if<
typename boost::mpl::contains_c<
boost::mpl::vector_c<int, state2, state3>
, N
>
, foo
>::type
set() { return foo(static_cast<state>(N)); }
private:
foo(state)
{
std::cout << "foo" << std::endl;
}
};
int main()
{
// Compiles, as expected.
foo f1 = foo::set<foo::state2>();
foo f2(foo::set<foo::state2>());
// Fail to compile, as expected.
// foo f3 = foo::set<foo::state1>();
// foo f4(foo::set<foo::state1>());
return 0;
}
Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net