2

I've been playing around with templates and would like to enforce that a template type given to a function has a particular static member. Unfortunately, there is no std::is_static type trait.

A rough example of how I would use it (or an alternative):

template<typename T>
void SomeFunc(T& obj)
{
    static_assert(std::is_static_v<decltype(T::someVariable)>, "someVariable must be static");
}

Are there any ways to achieve this kind of behaviour? I could just write

template<typename T>
void SomeFunc(T& obj)
{
    // must be static
    T::someVariable;
}

But this wouldn't be anywhere near as nice or informative as a static_assert with a decent message. This is just a syntax error of sorts :(

Thanks!

3
  • Of course, the best you can get here is a syntax error. The compiler is trying to resolve T::someVariable. If it cannot, of course it's a compiler error. There's no way around this. If you want to check if T::someVariable is a static member or a function, use type_traits header.
    – nakiya
    Commented May 23, 2017 at 1:57
  • That was my point - I couldn't figure out how to use type_traits to solve the problem :) But max66's answer seems to cover that.
    – HateDread
    Commented May 23, 2017 at 1:59
  • @HateDread - not sure the nakiya's objection but I've improved my answer.
    – max66
    Commented May 23, 2017 at 2:43

1 Answer 1

5

If I understand correctly what you want, you're looking for std::is_member_pointer (or the opposite of the value of std::is_member_pointer).

An example (also C++11 and C++14 compliant)

#include <type_traits>

struct foo
 { int value; };

struct bar
 { static int value; };

int main()
 {
   static_assert(
      true == std::is_member_pointer<decltype(&foo::value)>::value, "!");
   static_assert(
      false == std::is_member_pointer<decltype(&bar::value)>::value, "!!");
 }

-- EDIT --

Not sure to understand the nakiya's objection but ... in the following example I've developed a type traits (hasSomeValueStatic) that set value to true if the template argument has a someValue static member and false otherwhise (if someValue isn't static of there isn't someValue.

#include <iostream>
#include <type_traits>

struct foo
 { int someValue; };

struct bar
 { static int someValue; };

template <typename, typename = int>
struct hasSomeValueStatic : std::false_type
 { };

template <typename T>
struct hasSomeValueStatic<T, decltype(T::someValue, 0)>
      : std::integral_constant<bool,
           ! std::is_member_pointer<decltype(&T::someValue)>::value>
 { };

int main()
 {
   std::cout << hasSomeValueStatic<foo>::value << std::endl; // print 0
   std::cout << hasSomeValueStatic<bar>::value << std::endl; // print 1
   std::cout << hasSomeValueStatic<int>::value << std::endl; // print 0
 }
4
  • He/She wants to get a "Error message" instead of a compiler error when he/she tries to access a non-existing T::someVariable.
    – nakiya
    Commented May 23, 2017 at 1:58
  • @nakiya - not sure to understand your objection but... answer modified.
    – max66
    Commented May 23, 2017 at 2:42
  • Thanks max66, this is exactly what I was after! I'm not too worried about whether it exists, since there are earlier checks for that (not mentioned because I figured they weren't relevant to this very specific issue). Are there any limitations or gotchas of std::is_member_pointer that I should be worried about?
    – HateDread
    Commented May 23, 2017 at 2:54
  • @HateDread - about std::is_member_pointer, take in count that respond true when T::someValue is a static variable and when is a static function (method); if you want select only variables, give a look at std::is_member_object_pointer; anyway, give a look at the page in cppreference
    – max66
    Commented May 23, 2017 at 9:46

Not the answer you're looking for? Browse other questions tagged or ask your own question.