Étant donné le code suivant:

#include <iostream>

template <int X, int Y>
int foo(int v) // dummy parameter
{
    return v * X + v / Y; // dummy calculation
}

int main()
{
    // x, y, v are only known at runtime
    int x = 4;
    int y = 6;
    int v = 3;

    int result = 0;

    if (x == 1 && y == 1) result = foo<1, 1>(v);
    if (x == 1 && y == 3) result = foo<1, 3>(v);
    if (x == 5 && y == 1) result = foo<5, 1>(v);
    if (x == 4 && y == 6) result = foo<4, 6>(v);
    if (x == 8 && y == 4) result = foo<8, 4>(v);
    // ...

    std::cout << result << std::endl;
}

Je voudrais instancier foo pour différentes combinaisons de X et Y comme indiqué dans la cascade if de main.

Cela peut cependant devenir assez laid (long). Est-il possible d'utiliser C ++ 14 (par exemple en utilisant le préprocesseur) pour générer ce code étant donné une liste de combinaisons nécessaires?

0
Tobias Hermann 25 nov. 2017 à 11:10

3 réponses

Meilleure réponse

La génération du code et des instances pour les paires connues de x et y est facile si c'est exactement ce que vous voulez.

#define XYLIST \
X(1,1)\
X(1,3)\
X(5,1)\
X(4,6)\
X(8,4)
// etc.

#define X(X1, Y1) \
if (X1 == 1 && Y1 == 1) result = foo<X1, Y1>(v); else

XYLIST
{ throw "failed"; }

#undef X

Ajout d'un "autre" car il ne devrait pas y avoir deux lignes identiques. Et un "lancer" à la fin pour terminer la cascade else.

1
Surt 25 nov. 2017 à 08:56

Vous pouvez les convertir en expressions constantes. Si les valeurs incase sont connues à l'avance

#include <iostream>

template <int X, int Y>
int foo(int v) // dummy parameter
{
    return v * X + v / Y; // dummy calculation
}

int main()
{
    // x, y, v are only known at runtime
    const int x = 4;
    const int y = 6;
    int v = 3;

   int result = 0;

   result = foo<x, y>(v);


    std::cout << result << std::endl;
}

Cependant, les modèles ne sont pas des algorithmes à exécuter, mais des macros à développer pour produire du code. Je ne recommanderais pas d'utiliser un modèle pour le même type de données , dans ce cas, vous n'utilisez que int. Par conséquent, un modèle n'est pas particulièrement requis selon les normes de codage.

Passez ces valeurs dans une fonction elle-même.

Méthode 1: si vous ne disposez que de nombres entiers.

int foo(int v, int X, int Y) // dummy parameter
{
    return v * X + v / Y; // dummy calculation
}
int main()
{
    // x, y, v are only known at runtime
    int x = 4;
    int y = 6;
    int v = 3;

    int result = 0;

    result = foo(v,x,y);
}

Méthode 2: si quelque chose peut être transmis, c'est-à-dire, double type de données , etc.

template <typename T>
T foo(int v, T Y, T Y) // dummy parameter
{
    return v * X + v / Y; // dummy calculation
}
0
Shivansh Jagga 25 nov. 2017 à 09:22

Ceci est une version utilisant la récursivité.

#include <iostream>
#include <utility>
#include <stdexcept>

template <int X, int Y>
int foo(int v) // dummy parameter
{
    return v * X + v / Y; // dummy calculation
}

template <std::size_t index = 0>
int foo(int x, int y, int v) {
    constexpr std::pair<int, int> numbers[] = {{1, 1}, {1, 3}, {5, 1}, {4, 6}, {8, 4}};
    if constexpr (index < sizeof numbers / sizeof *numbers) {
        if (numbers[index].first == x && numbers[index].second == y) {
            return foo<numbers[index].first, numbers[index].second>(v);
        }
        return foo<index + 1>(x, y, v);
    } else { //no match
        throw std::runtime_error("No matching pair found");
    }
}

int main() {
    // x, y, v are only known at runtime
    int x = 4;
    int y = 6;
    int v = 3;

    int result = foo(x, y, v);

    std::cout << result << std::endl;
}

Si vous n'avez pas C ++ 17, vous pouvez remplacer if constexpr par la distribution de balises. Clang et gcc parviennent à optimiser le code à partir de -O1.

3
nwp 25 nov. 2017 à 09:44
47483884