【问题标题】:How to remove const ref modifiers for each element in typename... T如何删除类型名中每个元素的 const ref 修饰符... T
【发布时间】:2015-04-11 07:12:43
【问题描述】:

我刚开始用可变参数版本替换我的一些旧模板以避免代码重复(或丑陋的宏),因为参数数量可变。

我遇到但尚未解决的一个问题是:如何从属于“混合类型名...”的任何类型中删除 const&?

这是我的例子:

    #include <tuple>

    // old version to be replaced
    namespace old_version
    {
        template<typename T> struct struct_const_deref { typedef T Type; };
        template<typename T> struct struct_const_deref < const T& > { typedef T Type; };

        template < typename F, typename T1 >
        void exec(F* pObj, void(F::*pFct)(T1))
        {
            typename struct_const_deref<T1>::Type t1;

            // some code that fills t1

            (pObj->*pFct)(t1);
        }

        template < typename F, typename T1 , typename T2 >
        void exec(F* pObj, void(F::*pFct)(T1, T2))
        {
            typename struct_const_deref<T1>::Type t1;
            typename struct_const_deref<T2>::Type t2;

            // some code that fills t1, t2

            (pObj->*pFct)(t1, t2);
        }
    }

    // new variadic version
    namespace variadic 
    {
        template< typename... Args > struct struct_const_deref_tuple { typedef std::tuple< Args... > Tuple; };
        template< typename... Args > struct struct_const_deref_tuple < const Args&... > { typedef std::tuple< Args... > Tuple; };

        template < typename F, typename... Args >
        void exec(F* pObj, void(F::*pFct)(Args... args))
        {
            typename struct_const_deref_tuple< Args... >::Tuple tN;

            // some code that fills tN

            // some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
        }
    }

    struct Test
    {
        void foo(int i) {}
        void bar(const float& f, const int& i) {}
        void buu(const float& f, int i) {}
    };



    int main(int argc, char* argv[])
    {
        Test t;

        old_version::exec(&t, &Test::foo); // ok
        old_version::exec(&t, &Test::bar); // ok
        old_version::exec(&t, &Test::buu); // ok

        variadic::exec(&t, &Test::foo); // ok
        variadic::exec(&t, &Test::bar); // ok
        variadic::exec(&t, &Test::buu); // fails (the struct_const_deref_tuple does not 'catch' my case; 'tN' will be std::tuple<const float&, int>

        return 0;
    }

由于旧的解决方案需要每个参数数量的版本,我想用可变参数解决方案替换它。

不幸的是,可变参数版本失败了

Test::buu

因为 tN 变成了

std::tuple<const float&, int> 

但显然需要

std::tuple<float, int> 

让我工作。

欢迎任何想法:)

【问题讨论】:

标签: c++ variadic-templates stdtuple


【解决方案1】:

本质问题是pack expansion。此外,为简单起见,您可以使用 type_traits 中的 std::decay(c++11) 或 std::decay_t (c++14) 。以下代码应使用 c++14 编译。

#include <tuple>
#include <type_traits>

// new variadic version
namespace variadic
{
    template < typename F, typename... Args >
    void exec(F* pObj, void(F::*pFct)(Args... args))
    {
        std::tuple<std::decay_t<Args>...> tN;

        // some code that fills tN

        // some helper template that 'extracts' the tuple and calls (pObj->*pFct)(ExtractedArgs...)
    }
}

struct Test
{
    void foo(int i) {}
    void bar(const float& f, const int& i) {}
    void buu(const float& f, int i) {}
};



int main(int argc, char* argv[])
{
    Test t;

    variadic::exec(&t, &Test::foo); // ok
    variadic::exec(&t, &Test::bar); // ok
    variadic::exec(&t, &Test::buu); // ok

    return 0;
}

【讨论】:

  • 嘿,这很快,正是我想要的,非常感谢!对您的答案的一个建议:您可以将评论//失败(...)更改为类似 // now ok too 或在答案代码中类似:)
  • @Xor 我在一些评论后更改了它。谢谢!
【解决方案2】:

请看这里

#include <type_traits>

template<typename T>
struct RemoveConst;

template<typename T>
struct RemoveConst{
    using type = typename std::remove_const<T>::type;
};

template<typename T>
struct RemoveConst<const T>{
    using type = typename RemoveConst<T>::type;
};

template<typename T>
struct RemoveConst<const T*>{
    using type = typename RemoveConst<T>::type*;
};

template<typename T>
struct RemoveConst<T* const>{
    using type = typename RemoveConst<T>::type*;
};

template<template <typename...> class T, typename... Args>
struct RemoveConst<T<Args...>>{
    using type = T<typename RemoveConst<Args>::type...>;
};

这些类递归地从给定类型以及模板类的所有模板参数中删除const

demo

【讨论】:

  • 非常好的解决方案!
猜你喜欢
  • 2018-09-14
  • 2012-04-03
  • 2016-09-09
  • 2021-12-13
  • 2019-05-25
  • 2023-03-25
  • 2022-06-16
  • 2017-03-25
相关资源
最近更新 更多