This is what I have tried thus far:
Here is my code:
template<typename T1>
struct Foo
{
template<typename T2>
using MyPair = std::pair<T1, T2>;
using MyPairs = std::vector<MyPair>;
Foo()
{
//if T1 is an int, then I want T2 to be a double.
//if T1 is a float, then I want T2 to be an int.
}
};
I would like T2 to be a double if T1 is an int.
I would like T2 to be an int if T1 is a float.
How am I able to do this?
There are many ways to solve this.
The simple way is to use std::conditional to define the alias for T2. In which if the T1 == int the T2 will be double, all other types the T2 will be an alias for int. (See a demo)
#include <utility>
#include <type_traits> // std::conditional, std::is_same
template<typename T1>
struct Foo /* final */
{
static_assert(std::is_same<T1, int>::value || std::is_same<T1, float>::value, "NOT A VALID TYPE T1");
using T2 = typename std::conditional<std::is_same<T1, int>::value, double, int>::type;
using MyPair = std::pair<T1, T2>;
};
If you want to restrict the instantiation of the class for other types, provide a conditional instantiation of the class or a static_assert.
You can use traits specialization to define the T2 type. (See a demo)
#include <vector>
#include <utility>
// base template!
template <typename T1> struct helper_traits;
template <> // when helper_traits<`T1 == int`> then `T2 == double`
struct helper_traits<int> final { using T2 = double; };
template <> // when helper_traits<`T1 == float`> then `T2 == int`
struct helper_traits<float> final { using T2 = int; };
template<typename T1>
struct Foo /* final */
{
using T2 = typename helper_traits<T1>::T2; // will select the proper one!
using MyPair = std::pair<T1, T2>;
};
In c++17, using the if constexpr you could decide which type to be returned in the function, and use it to know the type of T2 as follows:
(See a demo)
#include <type_traits> // std::is_same_v
template<typename T1>
struct Foo /* final */
{
template<typename Type>
static constexpr auto typeHelper() noexcept
{
if constexpr (std::is_same_v<Type, int>)
return double{};
else if constexpr (std::is_same_v<Type, float>)
return int{};
}
using T2 = decltype(Foo<T1>::typeHelper<T1>()); // will select the proper one!
using MyPair = std::pair<T1, T2>;
};
This solution hasn't a nested template but works as you expect:
template<typename T1,
class = std::enable_if_t<std::is_same<T1, int>::value || std::is_same<T1, float>::value>>
struct Foo {
typedef typename std::conditional<std::is_same<T1, int>::value, double, int>::type T2;
using MyPair = std::pair<T1, T2>;
using MyPairs = std::vector<MyPair>;
MyPairs elements;
Foo() {
//if T1 is an int, then I want T2 to be a double.
//if T1 is a float, then I want T2 to be an int.
std::cout << typeid(T2).name() << std::endl;
}
};
int main()
{
Foo<int> f;
f.elements.push_back (std::make_pair(1.4, 2.3));
std::cout << f.elements[0].first << ", " << f.elements[0].second << std::endl;
return 0;
}
Output:
d
1, 2.3
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With