Jump to content
  • Advertisement
Sign in to follow this  
swiftcoder

SFINAE equivalent in C#?

This topic is 2262 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I've just started mucking with C# generics, and it seems that I'm running headlong into their limitations. In C++ I can do something like this:
template <typename T>
void Write(T data) {
int size = T.SizeInBytes;
// ...
}

And I can call Write() with any type that contains an integer-compatible member variable named 'SizeInBytes'. If one tries to do the same in C#:
public void Write<T>(T data) where T : struct {
int size = T.SizeInBytes;
// ...
}

Then it errors out with "error CS0119: Expression denotes a `type parameter', where a `variable', `value' or `type' was expected". Quite reasonably, since C# doesn't allow the use of expressions with generic types which can't be applied solely given the constraints.

Are there any common idioms to working around this? Assuming that (a) I need to work with value types, and (b) these structs are defined in a 3rd party library (i.e. I can't modify the definition of the struct itself).

Share this post


Link to post
Share on other sites
Advertisement
I believe Marshal.SizeOf and the typeof() operator should do what you need, it's been a while since I've used it though and I'm not sat in front of a computer I can test this on, but hopefully the following should work.


int size = Marshal.SizeOf(typeof(T));
Edited by adt7

Share this post


Link to post
Share on other sites
I've had similar problems a few times, usually it ends up as an unholy mess of generics and reflection.

Share this post


Link to post
Share on other sites

I've had similar problems a few times, usually it ends up as an unholy mess of generics and reflection.

Ja, I'm quickly starting to miss C++ templates.

I'm going to have to unlearn my template-centric coding style for C#.

Share this post


Link to post
Share on other sites

Ja, I'm quickly starting to miss C++ templates.

I'm going to have to unlearn my template-centric coding style for C#.

There's a number of aspects of C++ templates that bug me. Stuff like this in particular:
[source lang="cpp"]void function(const std::vector&lt;Objects*&gt;&){}
void constFunction(const std::vector&lt;const Objects*&gt;&){}

std::vector&lt;Objects*&gt; objectList;
function(objectList);
constFunction(objectList); // compile error[/source]

Do C# generics let you do that sort of stuff easily?

Share this post


Link to post
Share on other sites

[quote name='swiftcoder' timestamp='1348869994' post='4984880']
Ja, I'm quickly starting to miss C++ templates.

I'm going to have to unlearn my template-centric coding style for C#.

There's a number of aspects of C++ templates that bug me. Stuff like this in particular:
[source lang="cpp"]void function(const std::vector&lt;Objects*&gt;&){}
void constFunction(const std::vector&lt;const Objects*&gt;&){}

std::vector&lt;Objects*&gt; objectList;
function(objectList);
constFunction(objectList); // compile error[/source]

Do C# generics let you do that sort of stuff easily?
[/quote]

There is no such thing as "const" in C#, so that's a non issue.
However, it's normal that it doesn't work in c++. An array of const objects is not all all the same type as an array of non const objects. You can't expect implicit conversion of those two types. If you want to guarantee what I suspect is your wanted behavior, you should use a container where the element access function/operator returns const member if the container is const:

[source lang="cpp"]object* array &lt object* &gt ::operator[](int i);
const object* array &lt object* &gt ::operator[](int i) const;[/source]
with those two functions:
[source lang="cpp"]void function(array &lt objects* &gt &){}
void constFunction(const array &lt objects* &gt &){}[/source]

Share this post


Link to post
Share on other sites
The relatively coarse-grained nature of generic constraints in C# / the CLI is my biggest annoyance with the platform. There's really no reason why the compiler couldn't infer method (and operator!) and property level constraints and simply require that all type arguments provide them.

Share this post


Link to post
Share on other sites

There is no such thing as "const" in C#, so that's a non issue.
However, it's normal that it doesn't work in c++. An array of const objects is not all all the same type as an array of non const objects. You can't expect implicit conversion of those two types.

I could expect it, given that the two objects should have both identical code and data, and one has an interface that is a subset of the other. The fact that it's so difficult to use one in place of the other is just a limitation imposed by poor design choices in the C++ template system.

If it C++ disallowed atrocities like this, the types would be compatible:
struct MyObject{};

template<class T> struct MyTemplateClass {
T x;
};

template<> struct MyTemplateClass<const MyObject*>{};

int main()
{
MyObject obj;

MyTemplateClass<MyObject*> i1;
i1.x= &obj;

MyTemplateClass<const MyObject*> i2;
i2.x= &obj; // compile error
}


Reading through stuff about C# generics, it seems that they maintain restrictions to prevent that sort of thing.

Share this post


Link to post
Share on other sites

The relatively coarse-grained nature of generic constraints in C# / the CLI is my biggest annoyance with the platform. There's really no reason why the compiler couldn't infer method (and operator!) and property level constraints and simply require that all type arguments provide them.


As far as I can tell, the reason C# generics have the limitations they do is because they can be deployed in DLLs. This means that the compiled generic must work both for existing 'T' as well as unknown types that someone may cook up in the future (as long as those types fulfill all of the constraints the generic specifies). The compiler ensures that the generic can be used by anything that supports those constraints, without needing to actually be instantiated like C++ templates.

This is both their greatest strength and the cause of all of their weaknesses.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!