Drone2537
Drone2537

Reputation: 545

Declare a constexpr static member that is a function of a potentially-absent member in a template parameter?

I have a templated class for which I would like to provide a constexpr integer whose value is determined by the presence or absence of a constexpr integer in the template parameter:

template<typename Traits>
class Foo
{
  static constexpr int MaxDegree =
    std::conditional<
      std::is_integral<Traits::MaxDegree>::value,
      std::integral_constant<int, Traits::MaxDegree>,
      std::integral_constant<int, 0>
    >::value;
};

struct TraitA { };
struct TraitB { constexpr static int MaxDegree = 1; };

int main()
{
  std::cout
    << Foo<TraitA>::MaxDegree /* should be 0 */ << " "
    << Foo<TraitB>::MaxDegree; /* should be TraitB::MaxDegree == 1 */
    << "\n";
}

Obviously, this doesn't work since std::is_integral fails for TraitA. Is there anything that will work?

I'm constrained to c++11.

Upvotes: 0

Views: 70

Answers (1)

fabian
fabian

Reputation: 82461

Traits::MaxDegree

yields a compiler error, if the member doesn't exist. This means you cannot use this code as part of the expression directly.

You could use constexpr functions with SFINAE to implement this though:

template<class T>
constexpr typename std::enable_if<std::is_integral<decltype(T::MaxDegree)>::value, int>::type GetMaxDegree()
{
    return T::MaxDegree;
}

template<class T>
constexpr int GetMaxDegree(...) // this one is only used, if the first version results in a substitution failure 
{
    return 0;
}


template<typename Traits>
class Foo
{
public:
    static constexpr int MaxDegree = GetMaxDegree<Traits>();
};

Upvotes: 1

Related Questions