A Coder’s Corner

Blog de tecnologia y programación

Custom Sorting for ListBox in C#

Posted by gfaraj on July 31, 2008

Applying a custom sort to a Windows Forms ListBox is not a trivial task. One would think setting the Sorted property to true and implementing the IComparable interface in the item class would be enough. Well, it’s not that simple. Custom sorting a ListBox requires a new implementation of the whole sorting algorithm, by deriving ListBox and overriding the protected Sort method. The following code illustrates how you would override Sort and implement a quicksort algorithm that sorts the items according to their IComparable implementation. Don’t forget that Sort is only called when the Sorted property goes from false to true.

protected override void Sort()
{
    QuickSort(0, Items.Count - 1);
}

private void QuickSort(int left, int right)
{
    if (right > left)
    {
        int pivotIndex = left;
        int pivotNewIndex = QuickSortPartition(left, right, pivotIndex);

        QuickSort(left, pivotNewIndex - 1);
        QuickSort(pivotNewIndex + 1, right);
    }
}

private int QuickSortPartition(int left, int right, int pivot)
{
    var pivotValue = (IComparable)Items[pivot];
    Swap(pivot, right);

    int storeIndex = left;
    for (int i = left; i < right; ++i)
    {
        if (pivotValue.CompareTo(Items[i]) >= 0)
        {
            Swap(i, storeIndex);
            ++storeIndex;
        }
    }

    Swap(storeIndex, right);
    return storeIndex;
}

private void Swap(int left, int right)
{
    var temp = Items[left];
    Items[left] = Items[right];
    Items[right] = temp;
}

Posted in C Sharp, Programación | Tagged: , , , , , , | 2 Comments »

Spread Firefox : Version 3.0

Posted by gfaraj on June 18, 2008

image Ha salido la nueva version de Firefox, el browser popular y open-source de Mozilla. El primer dia de lanzamiento ha recibido más de 8 millones de descargas a nivel mundial. La organización de Guinness World Records está viendo si ha llegado a ser un record mundial. Los invito a bajarlo de aqui y que de paso vean cuantas personas han bajado Firefox 3.0 de sus paises. Los numeros de Centro America y alrededores al momento de escribir este articulo son:

Honduras: 1,114
Guatemala: 4,481
El Salvador: 2,664
Costa Rica: 9,425
Mexico: 96,962
Panamá: 2,840

Posted in Tecnologia, Web | Tagged: , , , , , | Leave a Comment »

iPhone tiene problemas con el Caller-ID afuera de USA

Posted by gfaraj on May 6, 2008

En regiones que no usan 10 digitos para un numero telefonico, el iPhone no puede identificar el contacto que esta llamando o mandando un SMS. Existen patches que ayudan, pero no terminan de arreglar el problema. De todos modos, deberian instalar AppSupport Patch, el cual lo pueden encontrar en el Installer en la categoria Tweaks (1.1.4). Este patch hace que el iPhone reconozca numeros que vienen en la forma +YYYXXXXXXXX, donde YYY es el codigo de pais. Ahora, el problema todavia existe si en tus contactos has almacenado los numeros sin este formato. Por esta razon, hice iContactFix.

El iPhone puede sincronizar contactos con Microsoft Outlook. iContactFix es un programa sencillo que se comunica con Outlook para modificar los numeros de telefono de los contactos. Por los momentos, el fix es unicamente intencionado para ser usado en Honduras. Pero seguramente podrian cambiar el programa para satisfacer las necesidades de otros paises.

Antes de correrlo, asegurense que tienen las opciones de telefono correctamente puestas en Windows. En Vista, se van a Start->Control Panel->Phone and Modem Options. Ahi modifiquen la “location,” o agreguen una nueva si no existe, y ponganle que estan en Honduras. Eso es todo. Si despues de correrlo, los contactos no tienen el simbolo + al principio, entonces es porque no han hecho este paso correctamente.

El codigo y el ejecutable se encuentran aqui.

Posted in Tecnologia | Tagged: , , , | 2 Comments »

Deploying a Symfony Project on GoDaddy Shared Hosting

Posted by gfaraj on April 25, 2008

Recently, I had the task of deploying my Symfony project on my GoDaddy shared Linux hosting. I ran into some problems, and I thought I would share in hope of helping any other poor soul who might run into the same problems.

First of all, you should follow the steps here. It does not require you to freeze the project to deploy it. I find that useful for projects that are not yet stable and need to deploy a “beta” version. Also, make sure you have PHP 5 as the default in your GoDaddy Hosting settings.

Next, you need to modify the .htaccess file. Go ahead and uncomment the RewriteBase line in the default symfony .htaccess file:

  # uncomment the following line, if you are having trouble
  # getting no_script_name to work
  RewriteBase /

This should prevent ‘www.myhost.com/mymodule’ from getting a 404 error from GoDaddy. Now, at least you might get forwarded to your 404 module/action. This is, at least, some proof that you’re moving forward. If you turn on logging (logging is turned off for production configurations by default), you might see the following:

  1	Info Context	initialization
  2	Info Controller	initialization
  3	Info Routing	match route [default_index] "/:module"
  4	Info Request	request parameters array ( 'module' => 'index.php', 'action' => 'index',)
  5	Info Controller	dispatch request
  6	Info Controller	action "indexphp/index" does not exist

As you can see, the module/action resolution is very wrong. This, of course, results in Symfony forwarding to your 404 module/action. Well, it turns out that adding one line to your php5.ini fixes this.

  cgi.fix_pathinfo = 1

This worked nicely for me, and I hope it works for you. I’m posting my full php5.ini and .htaccess files for completeness.

Addendum
It has come to my attention that some people are still having problems after making the changes described here. You might want to try one more change. In your application’s config/settings.yml file, set the following setting:

prod:
  .settings:
     path_info_key: REDIRECT_URL


php5.ini

register_globals = off
allow_url_fopen = off

expose_php = Off
max_input_time = 60
variables_order = "EGPCS"
extension_dir = ./
upload_tmp_dir = /tmp
precision = 12
SMTP = relay-hosting.secureserver.net
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=,fieldset="
memory_limit = 20000000
session.gc_maxlifetime = 72000

#log_errors = On
#error_log = php_error.log
#display_errors = On
#error_reporting  =  E_ALL

magic_quotes_gpc = false
cgi.fix_pathinfo = 1

[Zend]
zend_extension=/usr/local/zo/ZendExtensionManager.so
zend_extension=/usr/local/zo/4_3/ZendOptimizer.so

.htaccess

Options +FollowSymLinks +ExecCGI

  RewriteEngine On

  # uncomment the following line, if you are having trouble
  # getting no_script_name to work
  RewriteBase /

  # we skip all files with .something
  RewriteCond %{REQUEST_URI} \..+$
  RewriteCond %{REQUEST_URI} !\.html$
  RewriteRule .* - [L]

  # we check if the .html version is here (caching)
  RewriteRule ^$ index.html [QSA]
  RewriteRule ^([^.]+)$ $1.html [QSA]
  RewriteCond %{REQUEST_FILENAME} !-f

  # no, so we redirect to our front web controller
  RewriteRule ^(.*)$ index.php [QSA,L]

# big crash from our front web controller
ErrorDocument 500 "<h2>Application error</h2>symfony application failed to start properly"

Posted in Web | Tagged: , , , , | 105 Comments »

Random Ramblings : Religion

Posted by gfaraj on January 30, 2008

Why is everyone so sure about unproven theories? Atheists are completely sure there are no gods; theists are sure that there is a god or gods. In fact, they are so sure, they’re willing to fight and even kill to defend their beliefs.

“Did Sam kill the cat?” I don’t know.  “Does God exist?” I don’t know. Don’t be afraid of not knowing, it’s the only state of mind which will allow you to look for the truth.

But how are you certain that you’re right? “It’s called faith, I feel it in my heart.” Yes, I also have faith that tomorrow I’ll win the lottery, but that doesn’t make it true, nor more probable.

I respect everyone’s right to believe in whatever they please; the problem is that you don’t. Why do you have to push your beliefs onto everyone else? Is it maybe because deep-down inside you’re really not sure about your beliefs and don’t want to be the only one. A lie believed by many becomes truth; or so you might think.

Anyways, I think it’s enough for today.

Posted in Off-topic | 4 Comments »

Boost.Bind Ala Javascript

Posted by gfaraj on January 18, 2008

I’ve recently started learning Javascript. As a C++ programmer, I thought I’d write a Javascript version of Boost.Bind; just for fun. Javascript closures make this a fairly simple task, actually.

Let’s get right into the code.

 
function bind(f)
{
    if (f === null)
        return function() {};

    var args = Array.prototype.slice.call(arguments);
    args.shift();

    return function ()
    {
        var argsCopy = args.slice(0);
        var start = expandArgs(argsCopy, arguments);
        return f.apply(null, argsCopy.concat(Array.prototype.slice.call(arguments, start)));
    };
}

Simple enough? The expandArgs function will be shown at the end. Now for some example usage.

function foo(a, b, c)
{
    alert(a + ', ' + b + ', ' + c);
}

bind(foo, 1)(2, 3);  // 1, 2, 3 bind(foo, 1, 2)(3);  // 1, 2, 3 bind(foo, _3, _2, _1)(1, 2, 3);  // 3, 2, 1 bind(foo, _2, _2, _2)(1, 2, 3);  // 2, 2, 2 bind(foo, _2, 10)(1, 2, 3);  // 2, 10, 3

Another function, called bindMember, will bind a function to an object, so the this object refers to it. It also does the same parameter binding as the original bind.

 
function bindMember(f, o)
{
    if (f === null)
        return function() {};
    else if (o === null)
        return f;

    var args = Array.prototype.slice.call(arguments);
    args.shift();
    args.shift();

    return function ()
    {
        var start = 0;

        if (o.constructor == BindArg)
        {
            var arg = o.index;
            o = arguments[arg - 1];
            if (arg > start)
                start = arg;
        }

        var argsCopy = args.slice(0);
        start = expandArgs(argsCopy, arguments, start);
        return f.apply(o, argsCopy.concat(Array.prototype.slice.call(arguments, start)));
    };
}

As you can see, it’s very similar to bind, except it does an extra check to see if the object passed was a bind-argument. Here are some examples of its usage.

var o = { name : 'someobject' };

function foo(a, b, c)
{
    alert(this.name + ', ' + a + ', ' + b + ', ' + c);
}

bindMember(foo, o, 1)(2, 3);  // someobject, 1, 2, 3 bindMember(foo, o, 1, 2)(3);  // someobject, 1, 2, 3 bindMember(foo, o, _3, _2, _1)(1, 2, 3);  // someobject, 3, 2, 1 bindMember(foo, _1, 10, _2, _3)(o, 1, 2);  // someobject, 10, 1, 2

That’s it. Be aware that this was merely done as an experiment, with the purpose of learning Javascript. I have not done any benchmarks to study the efficiency of these functions. If anyone has time to do them, please let me know the results. 🙂

Note that you could also make these functions part of the Function prototype, if you wish. That would allow writing foo.bind(1)(2, 3) if you find that more readable.

The rest of the code is as follows:

function BindArg(i)
{
    this.index = i;
}

for (var i=1; i < 10; ++i)
{
    var arg = new BindArg(i);
    this['_' + i] = arg;
}

function expandArgs(args, arguments, start)
{
    if (start == null)
        start = 0;

    for (var i=0; i < args.length; ++i)
    {
        if (args[i] && args[i].constructor == BindArg)
        {
            var arg = args[i].index;
            if (arg > 0 && arg <= arguments.length)
            {
                args[i] = arguments[arg - 1];
                if (arg > start)
                    start = arg;
            }
            else                 args[i] = null;
        }
    }

    return start;
}

Posted in Javascript | Tagged: , , , , | 4 Comments »

Populoria – Tu guia local

Posted by gfaraj on December 30, 2007

Hola todos,

Ayudenme a probar un sitio que he estado haciendo. Se llama Populoria y es un sitio colaborativo que intenta reunir informacion de lugares y eventos locales. Por ahorita, estan las ciudades mas importantes de los paises latino americanos, pero a medida que se ocupe se pueden agregar mas ciudades y paises.

El sitio es: www.populoria.com

El sitio todavia no está totalmente terminado. Les agradeceria que lo probaran y si encuentran problemas o sugerencias, que me las comuniquen, preferiblemente por medio del Bugtrack (en el menu hay uno que dice “beta” y abajo de ese esta “bugtrack”).

Gracias!

Posted in Off-topic | Tagged: , , , , , , , | Leave a Comment »

Functors

Posted by gfaraj on November 2, 2007

En C++ le llamamos functors a objectos que pueden actuar como funciones. Esto se logra por medio de la sobrecarga al operator(), que permite cualquier cantidad de parametros. Ahora, ¿para qué usamos functors? Son utiles mas que todo cuando se ocupa una funcion que guarde estado. Por ejemplo, una funcion que revise si sus dos parametros son iguales.

bool equal(int x, int y) 
{
  return x == y; 
}

A esta funcion siempre hay que pasarle dos parametros. Es una funcion bien sencilla, y no es de mucha utilidad ya que hace lo mismo que el operator==. Ahora, ¿qué tal si queremos llamar a la funcion varias veces con el mismo parametro para x, pero cambiar y? Usamos un functor para guardar el valor de x.

struct equal 
{
  int x;
  equal(int x) : x(x) {}

  bool operator()(int y) const
  {
      return x == y;
  } 
}; 

int main()
{
  equal e(10);
  e(10); // 10 == 10
  e(2); // 10 == 2
  e(-10); // 10 == -10 
}

La estructura equal es un functor. La podrias usar para pasarla a los algoritmos de la libreria estandar. Por ejemplo, para buscar un elemento de cierto valor en un vector.

Nota: Algunos algoritmos de la libreria estandar tienen requerimientos para los functors. Para mas informacion, lean sobre std::unary_function y std::binary_function.

int main() 
{
  std::vector<int> v(10, 15);
  find_if(v.begin(), v.end(), equal<int>(10)); 
}

Si ya saben un poco de la libreria estandar, van a saber que ya existe una funcion std::find, que hace esto sin necesidad de un functor. Lo util de hacerlo en un functor es que se puede encadenar con otros functors. Por ejemplo, se puede hacer un functor not_, de modo que not_(equal<int>(10)) sea igual que usar el operator!=. De hecho, ya existen std::equal y std::not1. Ahora, para hacerlo bien y con templates:

template <typename T> 
struct equal_t 
{
  T x;
  equal_t(T const& x) : x(x) {}

  template <typename Y>
  bool operator()(Y const& y) const
  {
      return x == y;
  }
}; 

// Esto nos permite hacer equal(valor) en vez de equal_t<tipo>(valor) 
template <typename T> 
equal_t<T> equal(T const& x) 
{
  return equal_t<T>(x);
} 

// Sobrecarga para que funcione equal("hola") 
template <typename T, int N> 
equal_t<T const*> equal(T const (&x)[N]) 
{
  return equal_t<T const*>(x); 
} 

int main() 
{
  std::vector<std::string> v(10, "hola");
  find_if(v.begin(), v.end(), equal("mundo")); 
}

Esa clase soporta cualquier tipo que tenga sobrecargado el operator==. Esto se puede extender mucho mas que lo que hemos visto aqui. Más adelante explicaré como se implementan functors más complicados, como los que se ven en Boost.Bind.

Posted in C++ | 3 Comments »

Como Hacer Aplicaciones en Facebook

Posted by gfaraj on September 11, 2007

Facebook es una comunidad en linea originalmente orientada a estudiantes de universidad, que ahora esta abierta al publico. Facebook te permite, a traves de su extenso API, crear aplicaciones que todos sus usuarios pueden usar. Aqui vamos a ver como crear una aplicacion, usando una que yo hice de ejemplo. Pueden agregar la aplicacion de ejemplo, aqui. Si necesitan mas información, visiten estas paginas:

Tomen en cuenta que Facebook no les da web hosting para su aplicacion, asi que tendran que conseguirlo aparte. Si necesitan una base de datos, ésta tendrá que ser aparte también. Vayan aqui y agreguen el Developer application a su Facebook. Ahora ya pueden pedir una nueva llave para su aplicacion. Esta llave se usa para identificar únicamente a su aplicacion. Si ya tienen el URL del servidor que usaran para la aplicacion, pueden ir agregandola ahi mismo. Una buena explicación de que poner en cada campo está aqui.

Desde este punto asumo que tienen listo el web hosting para la aplicación. Bajen el PHP (4 and 5) Client Library de aqui y ponganlo en el directorio de la aplicación.

Ahora, empezar a programar. La aplicación de ejemplo, Marquee, contiene 2 archivos importantes. Uno de ellos es config.php que tiene cosas comunes e inicialización. El otro es index.php que es la pagina principal de la aplicación.

config.php

<?php

require_once('client/facebook.php');

$fb_apikey = '<Aqui va el API key>';
$fb_secret = '<Aqui va el Secret>';

$facebook = new Facebook($fb_apikey, $fb_secret);
$user = $facebook->require_login();

$app_callbackurl = 'http://www.tuservidor.com/marquee/';

try
{
    if (!$facebook->api_client->users_isAppAdded())
        $facebook->redirect($facebook->get_add_url());
}
catch (Exception $ex)
{
    $facebook->set_user(null, null);
    $facebook->redirect($app_callbackurl);
}

// Incluye la clase Database que simplemente es// una utilidad que hice para consultar una base de datos
require_once('database.php')

?>

Como pueden ver, este archivo es bien sencillo. Preparamos las cosas comunes que se usaran en otros lugares.

Antes de proseguir, tendremos que introducir un termino: FBML. FBML, Facebook Markup Language, es un lenguaje basado en XML que es usado para facilitar la integración de las aplicaciones en Facebook. Provee muchas funciones que son bien utiles para los desarrolladores.

Si tu aplicación quiere poner una caja en el perfil del usuario, vas a tener que llamar la función profile_setFBML. Como el nombre lo sugiere, esta función agarra de parametro el codigo FBML que ira en esa caja. Si se manda una cadena vacia, la caja desaparece del perfil del usuario.

index.php

<?php

require_once('config.php');
require_once('marquee.php');

if (isset($_REQUEST['marquee_text']))
{
    $text = $_REQUEST['marquee_text'];

    $fbml = '<fb:fbml version="1.1">' .
                '<fb:subtitle>' .
                    '<fb:action href="http://www.facebook.com/apps/application.php?api_key=2bc05a98791e24c98c9b5c94407664d8">Home</fb:action>' .
                    '<fb:action href="http://apps.facebook.com/marquee">Marquee</fb:action>' .
                '</fb:subtitle>' .
                '<a href="http://apps.facebook.com/marquee">' .
                get_marquee_code($text) .
                '</a>' .
            '</fb:fbml>';

    $facebook->api_client->profile_setFBML($fbml, $user);

    $database = new Database();
    $database->query("update fb_marquee set value='" . $database->quote($text) . "' where uid = $user");
}
else
{
    $database = new Database();
    $result = $database->query("select * from fb_marquee where uid = $user");
    if (sizeof($result) == 0)
    {
        $text = "Hello, world!";
        $result = $database->query("insert into fb_marquee (uid, value) values ($user, '" . $database->quote($text) . "')");
    }
    else
    {
        $text = $result[0]->value;
    }
}

?>

<div style="margin: 10px;">

<fb:dashboard>
  <fb:create-button href="invite.php">Invite your friends!</fb:create-button>
</fb:dashboard>
<br />

<div style="width: 50%">
Add a scrolling LED marquee to your profile to let your friends know what's going on. Announce it!
</div>

<br />
<br />

<div style="width: 100%; margin-left: 20%; margin-right: 20%;">
<span style="text-align: center;"><b>Preview</b></span><br />
<?php
    echo get_marquee_code($text);
?>
</div>

<br />
Enter the text you want shown in the marquee. <br />
Enter each message in its own line; they will be separated appropriately.<br />
<br />
<form action="" method="get">
    <textarea name="marquee_text" cols="50" rows="7"><?php echo $text; ?></textarea><br />
    <input name="submit" type="submit" value="Save">
</form>

</div>

Este archivo es un poco más grande, pero si lo ven bien es PHP sencillo con elementos de XHTML y FBML al final. La parte interesante es:

    $fbml = '<fb:fbml version="1.1">' .
                '<fb:subtitle>' .
                    '<fb:action href="http://www.facebook.com/apps/application.php?api_key=2bc05a98791e24c98c9b5c94407664d8">Home</fb:action>' .
                    '<fb:action href="http://apps.facebook.com/marquee">Marquee</fb:action>' .
                '</fb:subtitle>' .
                '<a href="http://apps.facebook.com/marquee">' .
                get_marquee_code($text) .
                '</a>' .
            '</fb:fbml>';

    $facebook->api_client->profile_setFBML($fbml, $user);

Aqui va el codigo que irá en la caja del perfil de usuario. Como pueden ver, tiene dos links (fb:action) en el subtitulo, uno es “Home” y el otro “Marquee”. Tambien, contiene el codigo que pone el marquee en la caja, a traves de la funcion get_marquee_code.

Asi se ve la caja:

image

Asi se ve index.php:

image
Espero esto haya ayudado a los que estan empezando a hacer aplicaciones de Facebook. Cualquier pregunta la pueden hacer a traves de comentarios en este articulo.

Addendum : Como Invitar Amigos

// Agarremos la lista de amigos que ya tienen la aplicacion instalada
$rs = $facebook->api_client->fql_query(
	"select uid " .
	"from user " .
	"where has_added_app=1 and uid IN " .
	"   (SELECT uid2 FROM friend WHERE uid1 = $user)");

$arFriends = "";

//  Construimos una lista de estos amigos
if ($rs)
{
	for ( $i = 0; $i < count($rs); $i++ )
	{
		if ($arFriends != "")
			$arFriends .= ",";
	
		$arFriends .= $rs[$i]["uid"];
	}
}

// El URL para referrals
$sNextUrl = urlencode("&refuid=" . $user);

//  Construimos el FBML que ira en el mensaje de invitacion
$invfbml = <<<FBML
You've been invited to add Marquee!
<fb:name uid="$user" firstnameonly="true" shownetwork="false"/> wants you to add Marquee to keep posted on your announcements!
<fb:req-choice url="http://www.facebook.com/add.php?api_key=$fb_apikey&next=$sNextUrl" label="Add Marquee!" />
FBML;

?>

<fb:request-form type="Marquee" action="index.php?c=skipped" content="<?=htmlentities($invfbml)?>" invite="true">
	<fb:multi-friend-selector max="20" actiontext="Here are your friends who don't have Marquee. Invite them to add it!" showborder="true" rows="5" exclude_ids="<?=$arFriends?>" />
</fb:request-form>

Posted in Programación, Tecnologia | 398 Comments »

Concepts

Posted by gfaraj on August 4, 2007

Una de las principales adiciones al lenguaje en el proximo estandar seran los Concepts. La libreria estandar tiene muchos conceptos que solo estan escritos en el documento. Para enforzarlos, es muy comun que los que implementan la libreria tengan que usar varios trucos que se pueden hacer tediosos y dificil de manejar. Ademas de eso, cuando un usuario de la libreria no cumple los requisitos de estos conceptos, los mensajes de error son bien dificil de interpretar, especialmente para alguien que acaba de empezar a aprender C++. Veamos un ejemplo:

#include <list>
#include <algorithm>

int main()
{
    std::list<int> l;
    std::sort(l.begin(), l.end());
}

Este codigo produce el siguiente error en Visual C++ 2005 (Nota: este codigo realmente produce 6 errores en este compilador, lo recorte por brevedad):

error C2784: 'reverse_iterator<_RanIt>::difference_type std::operator -(const std::reverse_iterator<_RanIt> &,const std::reverse_iterator<_RanIt2> &)' :
             could not deduce template argument for 'const std::reverse_iterator<_RanIt> &'
             from 'std::list<_Ty>::_Iterator<_Secure_validation>'

Un programador experienciado podria entender que sort esta tratando de usar el operator- con los iteradores, y ese operador solo es permitido para iteradores random-access. Los iteradores de list no son random-access, asi que no tienen este operador sobrecargado. Alguien que acaba de empezar C++ quedaria muy confundido y talvez no sabe que list tiene una funcion sort como miembro.

Aqui es donde entran los Concepts. Esos conceptos que solo estan escritos en los documentos del estandar podran ser expresados en codigo. Esto dara una mucho mejor manera para revisar requisitos de los templates. Por ejemplo, comparemos la declaracion de la funcion sort, usando la tipica actual con la que se usaria con concepts:

template <typename RanIter>
void sort(RanIter begin, RanIter end);   // actualidad

template <typename Iter>
requires RAIterator<Iter>
void sort(Iter begin, Iter end);         // usando concepts

template <RAIterator Iter>
void sort(Iter begin, Iter end);         // sintaxis alterno

En este ejemplo, RAIterator es un concept que representa un random-access iterator definido previo a la declaracion de sort. Volviendo al primer ejemplo, si usamos concepts, el mensaje de error reduciria considerablemente a algo asi:

error: no concept map for requirement RAIterator<std::_List_iterator<int>>

Esto es sin duda mucho mas claro que recibir 6 errores como vimos arriba. Pero, ¿son los concepts solo utiles para producir mejores mensajes de error? No, tienen mucho mas uso que eso. Como ilustración, veamos el ejemplo de enable_if que vimos en un articulo anterior, ahora usando concepts.

template <IsIntegral T>
typename T mod(T a, T b)        // #1
{
    return a % b;
}

template <IsFloat T>
T mod(T a, T b)                 // #2
{
    return std::fmod(a, b);
}

int main()
{
    mod(4, 2);             // OK, llama #1
    mod(1.0, 10.0);        // OK, llama #2
    mod("hola", "mundo");  // error
}

Pueden notar que este codigo es mucho más elegante que el que usa enable_if. Naturalmente, el error que muestra en la ultima linea será mucho mas claro también. Otra utilidad de los concepts es poder excluir ciertas funciones de una clase dependiendo de los requisitos que cumplan los parametros del template. Por ejemplo:

auto concept LessThanComparable<typename T> {
    bool operator<(T, T);
}

template <typename T>
struct list
{
    requires LessThanComparable<T> void sort();
};

struct X {};

void f(list<int> l1, list<X> l2)
{
    l1.sort();     // OK, 'int' cumple con LessThanComparable
    l2.sort();     // error, list<X> no tiene 'sort' porque X no tiene operator< definido
}

Aqui pueden ver como definir un concept, LessThanComparable, que define el requisito de tener operator< definido para T. El template list define una funcion sort solo si el tipo T cumple con los requisitos de LessThanComparable. Esto permite no deshabilitar toda la clase list solo por una funcion. Creo que eso es todo por hoy. Hay cosas que no vimos, como los concept maps y los axioms, pero tendrá que ser otro dia. Uno de los principales autores de Concepts es Douglas Gregor, y aqui esta su blog. Espero que esten igual de emocionados con esto como yo lo estoy. 🙂

Posted in C++, C++0x, Programación | Tagged: , , , , | Leave a Comment »