Autor Wątek: Typ wyniku działania (szablony)  (Przeczytany 1545 razy)

Offline karol57

  • Użytkownik

# Wrzesień 09, 2016, 16:00:48
Jak w C++ (może być nawet 1z, byle by na g++ działało) sprawdzić jaki jest typ wynikowy działania na dwóch typach?

Coś w stylu:
struct Temp { int operator*(double rhs); };
bool operator*(double lhs, const Temp& rhs);

using Type1 = ::std::get_sum_op_type_t<int, double>;  // Type1 == double
using Type2 = ::std::get_mul_op_type_t<Temp, double>; // Type2 == int
using Type3 = ::std::get_mul_op_type_t<double, Temp>; // Type3 == bool

Jak nie ma tego w standardzie to może w boost? Ew. jak w prosty sposób to napisać, bo nie mam już pomysłu jak zapytać o to Google.

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline kapustman

  • Użytkownik

  • +1
# Wrzesień 09, 2016, 17:17:02
Tak na szybko myśląc:

int a;
double b;

auto c = a + b; //dowolna operacja

using type = decltype(c); //type == double

EDIT:
To powinno działać
template<class R, class L>
struct sum_type
{
using type = decltype(static_cast<R>(0) + static_cast<L>(0));
};
« Ostatnia zmiana: Wrzesień 09, 2016, 20:33:10 wysłana przez kapustman »

Offline hashedone

  • Użytkownik

  • +2
# Wrzesień 09, 2016, 22:02:29
Rozwiązanie kapustmana zadziała tylko dla typów które dają się zainicjalizować zerem (dla tego co w przykładzie akurat się sprawdzi), natomiast bardziej generycznie:
typename std::result_of<decltype([](auto a, auto b) { return a + b; })(T1, T2)>::typeMożna owrapować na przykład tak:
template <typename T1, T2> using sum_type =
typename std::result_of<decltype([](auto a, auto b) { return a + b; })(T1, T2)>::type;
Nie kompilowałem, więc ewentualne literówki trzeba poprawić.
« Ostatnia zmiana: Wrzesień 09, 2016, 22:38:56 wysłana przez hashedone »

Offline Dab

  • Redaktor
    • blog

  • +3
# Wrzesień 10, 2016, 13:04:23
W C++11 (nie wymagając 14 i późniejszych) przejdzie takie coś:

template <typename A, typename B>
struct type_helper { A a; B b; using type = decltype(a + b); };

template <typename A, typename B>
using sum_type = typename type_helper<A, B>::type;

Działa też dla typów bez konstruktora domyślnego.

Offline karol57

  • Użytkownik

# Wrzesień 10, 2016, 21:27:17
Podziękował, rozwiązanie zaproponowane przez Daba wygląda na najprostsze i działa tak jak chciałem.

//EDIT: Co do rozwiązania zaproponowanego przez kapustamana
Cytuj
$ gcc a.cpp -std=c++1z
a.cpp:39:34: error: lambda-expression in unevaluated context
 typename std::result_of<decltype([](auto a, auto b) { return a + b; })(T1, T2)>::type;
...

Działa coś takiego: template <typename T1, typename T2>
inline auto sum_func(T1 a, T2 b) { return a+b; }

template <typename T1, typename T2> using sum_type =
typename std::result_of<decltype(sum_func<T1, T2>)&(T1, T2)>::type;

Ale rozwiązanie Daba zwraca dla += referencję co według mnie jest bardziej poprawne.

//EDIT2:
Dla auto& i auto&& nie działa w drugą stronę (+ zwraca referencję i warning)
« Ostatnia zmiana: Wrzesień 10, 2016, 21:44:30 wysłana przez karol57 »