1

In C++ I routinely use this templated function...

template<typename T>
bool isPowerOf2 (T x) // returns nonzero if x is a power-of-2
{
  return x && ((x & (~x + 1)) == x);
}

...and I'm trying to implement the same thing in C#. So here's the best I can come up with:

public class Utils
{
   // ...

   public static bool isPowerOf2<T>(T x) // returns true if x is a power-of-2
   {
      return (x != 0) && ((x & (~x + 1)) == x);
   }
}

But Visual Studio complains that error CS0019: Operator '!=' cannot be applied to operands of type 'T' and 'int' and error CS0023: Operator '~' cannot be applied to operand of type 'T'.

If I remove the generic stuff & just make it "public static bool isPowerOf2(int x)", it works fine (just like in various implementations here), but I'd like the implementation to be generic so it would work on any integer type.

Community
  • 1
  • 1
phonetagger
  • 7,701
  • 3
  • 31
  • 55

2 Answers2

5

This is a good illustration of why C# generics are not C++ templates. C# must be able to compile code without knowing T, while C++ could postpone compiling until the type of T is known. This lets C++ figure out how to perform ~, +, &, and so on.

The simplest approach with C# is to make multiple overloads for types that you plan to use with the function. This results in a small amount of code duplication, but it reads much better than other options, such as generating code dynamically with LINQ expressions.

If performance is not critical, you could also use Convert.ToInt64:

bool isPowerOf2 (object obj) {
    var x = Convert.ToInt64(obj);
    return x && ((x & (~x + 1)) == x);
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

C# does static type checking, this can be bypassed declaring dynamic type. You can still do what you want to do having input parameter is of type dynamic. Please note ~ works only on integers, fails for float and double.

public class Utils
{
   // ...

   public static bool isPowerOf2(dynamic x) 
   {
      return (x != 0) && ((x & (~x + 1)) == x);
   }
}

Check this example

Hari Prasad
  • 16,716
  • 4
  • 21
  • 35