Bonjour à tous,
Je viens quérir votre aide concernant une feature de C++14 qui est : std::make_unique<T>(args);
Je travaille sur un projet qui est compilé avec NVCC (Cuda 8.0) et qui doit fonctionner à la fois sur windows et linux. Nous utilisons les std::unique_ptr<T>
et avons naïvement commencé à utiliser std::make_unique<T>(args);
afin d’instancier nos objets.
Malheureusement, Cuda 8.0 n’autorise qu’au mieux C++11 avec GCC, ce qui ne permet donc pas d’utiliser les std::make_unique
. De son coté MSVC s’en sort un peu mieux puisqu’il n’a pas ce flag et permet d’utiliser toutes les features dont il dispose comme bon nous semble. Nous avons alors pensé une "parade" assez simple afin d’avoir une utilisation ressemblant à std::make_unique<T>(args);
et qui est create_unique_ptr<T>(args);
Voici l’implémentation :
1 2 3 4 5 6 7 8 9 10 11 12 13 | template<typename T, typename... Args> std::unique_ptr<T> create_unique_ptr(Args... args) { #if OS == WINDOWS return std::make_unique<T>(std::forward<Args>(args)...); #elif OS == LINUX std::unique_ptr<T> ptr; ptr.reset(new T(std::forward<Args>(args)...)); return ptr; #else static_assert(false, "OS ??"); #endif } |
Tout fier de nous, nous avons continué notre développement sans nous poser de questions et nous étions contents. Et c’est là que les problèmes arrivent, sans s’en rendre compte, utilisée ainsi nous créons une copie des arguments !! Ce qui pose évidemment problème en faisant des copies inutiles mais aussi pour les objets non-copiables. L’idée était alors d’utiliser les références, cependant si elles ne sont pas const
le compilateur nous crie dessus (à juste titre) lorsque nous passons des constantes. Il suffirait alors de rajouter const
mais vient alors un problème avec std::foward
qui ne trouve pas la bonne surcharge lorsque nous faisons appel aux constructeurs par défaut.
Les questions sont donc : Comment arriver à faire tout ça ? Est-ce la meilleur manière de faire ? Pouvons nous faire autrement ? Quel est votre avis ?
Merci à vous !
Cheers