Constrained genericity: Difference between revisions

Content added Content deleted
(Rename Perl 6 -> Raku, alphabetize, minor clean-up)
Line 53: Line 53:
-- We have declared Banana and Tomato as a Food.</lang>
-- We have declared Banana and Tomato as a Food.</lang>
The Tomato_Box can only contain tomatoes; the Banana_Box can only contain bananas. You can only create boxes of eatable objects.
The Tomato_Box can only contain tomatoes; the Banana_Box can only contain bananas. You can only create boxes of eatable objects.

=={{header|C++}}==
{{works with|C++11}}
Uses static assertion to disallow instantiations on incorrect types
<lang c++>
template<typename T> //Detection helper struct
struct can_eat //Detects presence of non-const member function void eat()
{
private:
template<typename U, void (U::*)()> struct SFINAE {};
template<typename U> static char Test(SFINAE<U, &U::eat>*);
template<typename U> static int Test(...);
public:
static constexpr bool value = sizeof(Test<T>(0)) == sizeof(char);
};

struct potato
{ void eat(); };

struct brick
{};

template<typename T>
class FoodBox
{
//Using static assertion to prohibit non-edible types
static_assert(can_eat<T>::value, "Only edible items are allowed in foodbox");

//Rest of class definition
};

int main()
{
FoodBox<potato> lunch;

//Following leads to compile-time error
//FoodBox<brick> practical_joke;
}</lang>


=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
Line 132: Line 94:
}
}
}
}
}</lang>

=={{header|C++}}==
{{works with|C++11}}
Uses static assertion to disallow instantiations on incorrect types
<lang c++>
template<typename T> //Detection helper struct
struct can_eat //Detects presence of non-const member function void eat()
{
private:
template<typename U, void (U::*)()> struct SFINAE {};
template<typename U> static char Test(SFINAE<U, &U::eat>*);
template<typename U> static int Test(...);
public:
static constexpr bool value = sizeof(Test<T>(0)) == sizeof(char);
};

struct potato
{ void eat(); };

struct brick
{};

template<typename T>
class FoodBox
{
//Using static assertion to prohibit non-edible types
static_assert(can_eat<T>::value, "Only edible items are allowed in foodbox");

//Rest of class definition
};

int main()
{
FoodBox<potato> lunch;

//Following leads to compile-time error
//FoodBox<brick> practical_joke;
}</lang>
}</lang>


Line 915: Line 915:
nom..nom..nom
nom..nom..nom
nom..nom..nom</pre>
nom..nom..nom</pre>

=={{header|Nim}}==
<lang nim>type
Eatable = concept e
eat(e)

FoodBox[e: Eatable] = seq[e]

Food = object
name: string
count: int

proc eat(x: int) = echo "Eating the int: ", x
proc eat(x: Food) = echo "Eating ", x.count, " ", x.name, "s"

var ints = FoodBox[int](@[1,2,3,4,5])
var fs = FoodBox[Food](@[])

fs.add Food(name: "Hamburger", count: 3)
fs.add Food(name: "Cheeseburger", count: 5)

for f in fs:
eat(f)</lang>


=={{header|Objeck}}==
=={{header|Objeck}}==
Line 939: Line 962:
}
}
}</lang>
}</lang>


=={{header|Nim}}==
<lang nim>type
Eatable = concept e
eat(e)

FoodBox[e: Eatable] = seq[e]

Food = object
name: string
count: int

proc eat(x: int) = echo "Eating the int: ", x
proc eat(x: Food) = echo "Eating ", x.count, " ", x.name, "s"

var ints = FoodBox[int](@[1,2,3,4,5])
var fs = FoodBox[Food](@[])

fs.add Food(name: "Hamburger", count: 3)
fs.add Food(name: "Cheeseburger", count: 5)

for f in fs:
eat(f)</lang>


=={{header|Objective-C}}==
=={{header|Objective-C}}==
Line 1,147: Line 1,146:
print MrG.WeightGain 'result 15.75
print MrG.WeightGain 'result 15.75
</lang>
</lang>

=={{header|Perl 6}}==
{{works with|Rakudo|2016.01}}

<lang perl6>subset Eatable of Any where { .^can('eat') };

class Cake { method eat() {...} }

role FoodBox[Eatable] {
has %.foodbox;
}

class Yummy does FoodBox[Cake] { } # composes correctly
# class Yucky does FoodBox[Int] { } # fails to compose

my Yummy $foodbox .= new;
say $foodbox.perl;</lang>
{{out}}
<lang>Yummy.new(foodbox => {})</lang>


=={{header|Phix}}==
=={{header|Phix}}==
Line 1,426: Line 1,406:
All the tests pass. Look at the tests to see what generates an exception (i.e.
All the tests pass. Look at the tests to see what generates an exception (i.e.
not allowed at runtime) and what does not.
not allowed at runtime) and what does not.

=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2016.01}}

<lang perl6>subset Eatable of Any where { .^can('eat') };

class Cake { method eat() {...} }

role FoodBox[Eatable] {
has %.foodbox;
}

class Yummy does FoodBox[Cake] { } # composes correctly
# class Yucky does FoodBox[Int] { } # fails to compose

my Yummy $foodbox .= new;
say $foodbox.perl;</lang>
{{out}}
<lang>Yummy.new(foodbox => {})</lang>


=={{header|Ruby}}==
=={{header|Ruby}}==