C ++ - Überladungsvorlage beim Zuweisen von Wert oder Rückruffunktion


8

Der Versuch, so etwas wie ...

template <class T>
struct Wrapper
{
    template <class U>
    void set(const U& u) { myT = u; }

    template <class F>
    void set(F f) { myT = f(); }

    T myT;
};

Ich weiß, dass ich hier SFINAE verwenden muss, aber wie unterscheide ich einen Rückrufparameter von einem Wertparameter? Es ist sicher anzunehmen, dass ein Wert nicht als Rückruf verwendet werden kann.

Ich habe versucht , enable_ifmit is_function, result_of, invoke_result, is_invocable, und andere, aber nichts davon richtig funktioniert. Ist es überhaupt möglich?

Antworten:


9

Sie können es ohne SFINAE tun:

template<class U>
void set(const U& u) { 
    if constexpr (std::is_invocable_v<U>)
        myT = u();
    else
        myT = u;
}

oder allgemeiner:

template<class U>
void set(U&& u) { 
    if constexpr (std::is_invocable_v<U>)
        myT = std::forward<U>(u)();
    else
        myT = std::forward<U>(u);
}

2
constexprwegen besserer Kompilierungszeiten SFINAE vorziehen
Dev Null

7

Ja, Sie können SFINAE mit Hilfe von std::is_invocable(seit C ++ 17) anwenden .

template <class U>
std::enable_if_t<!std::is_invocable_v<U>> set(const U& u) { myT = u; }

template <class F>
std::enable_if_t<std::is_invocable_v<F>> set(F f) { myT = f(); }

LEBEN


4

Die Überladung, die eine Funktion als Argument annimmt, kann wie folgt definiert werden:

template <typename R>
   void set(R (*f)())
   {
      myT = f();
   }

Demonstrativer Code:

#include <iostream>

template <class T>
struct Wrapper
{
   template <class U>
      void set(const U& u)
      {
         std::cout << "In set(const U& u)\n";
         myT = u;
      }

   template <typename R>
      void set(R (*f)())
      {
         std::cout << "In set(R (*f)())\n";
         myT = f();
      }

   T myT;
};

short foo()
{
   return 2u;
}

int main()
{
   Wrapper<int> a;
   a.set(1u);
   a.set(foo);
}

Ausgabe:

In set(const U& u)
In set(R (*f)())

1
Dies ist eine schlechte Lösung. Sie akzeptieren nur Funktionszeiger. Sie können weder Lambdas noch "aufrufbare Klassen" übergeben.
Bktero
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.