【问题标题】:Initialise class template depending on another template根据另一个模板初始化类模板
【发布时间】:2020-11-15 04:37:19
【问题描述】:

这是我迄今为止尝试过的:

这是我的代码:

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.
    }
};

如果T1int,我希望T2 成为double。 如果T1float,我希望T2 成为int

我怎么能做到这一点?

【问题讨论】:

  • 例如,using T2 = std::conditional_t&lt;std::is_same_v&lt;T1, int&gt;, double, int&gt;;

标签: c++ c++11 templates types class-template


【解决方案1】:

有很多方法可以解决这个问题。

选项 - 我

简单的方法是使用std::conditional 定义T2 的别名。其中如果T1 == int T2 将是double所有其他类型 T2 将是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>;
};

如果您想限制其他类型的类的实例化,请提供类的条件实例化或static_assert


选项-II

您可以使用特征特化来定义T2 类型。 (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>;
};

选项 - III

中,使用if constexpr可以决定在函数中返回哪个类型,并用它来知道T2的类型如下: (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>;
};

【讨论】:

    【解决方案2】:

    此解决方案没有嵌套模板,但可以按预期工作:

    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;
    }
    

    输出:

    d
    1, 2.3
    

    【讨论】:

    • using T2 = std::conditional_t&lt;std::is_same_v&lt;T1, int&gt;, double, int&gt;;
    • @bipll 是的,更符合 C++ 习惯。投票 +1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-08
    • 1970-01-01
    • 1970-01-01
    • 2022-01-05
    • 1970-01-01
    相关资源
    最近更新 更多