const-ness as template argument

后端 未结 3 1051
遇见更好的自我
遇见更好的自我 2021-02-07 23:59

I have two structs:

  // ----- non-const -----
  struct arg_adapter
  {
      EArgType type;  // fmtA, fmtB, ...

      union
      {
        TypeA * valueA;
            


        
相关标签:
3条回答
  • 2021-02-08 00:44

    I just stumbled about an even better way using the type selection ideom presentend by Alexandrescu in "Modern C++ Design":

    This is the type selector:

    template<bool flag, typename T, typename U>
    struct Select { typedef T Result; }
    
    template<typename T, typename U>
    struct Select<false, T, U> { typedef U Result; }
    

    Your class would then look like this:

    template<bool isConst>
    struct arg_adapter
    {
      // define A and B as const or non-const
      typedef typename Select<isConst, const TypeA, TypeA>::Result A;
      typedef typename Select<isConst, const TypeB, TypeB>::Result B;
    
      EArgType type;  // fmtA, fmtB, ...
    
      union
      {
        A * valueA; // this is either const TypeA* oder TypeA* depending on
                    // your choice of the isConst template parameter
        B * valueB;
        // ... more types
      }
    
      arg_adapter(A & value) : type(fmtA), valueA(&value) {} // same here with ref
      arg_adapter(B & value) : type(fmtB), valueB(&value) {}
      // ...
    }
    

    You can use typedefs for convenience:

    struct nonconst_adapter : public arg_adapter<false> {};
    
    struct const_adapter : public arg_adapter<true> {};
    

    This was my old answer using simple type traits:

    template<typename TypeTraits>
    struct arg_adapter
    {
      typedef typename TypeTraits::T T;
      void bar(T a) { ... } // by value/reference
      void bar(T* a) { ... } // by pointer
    }
    
    template<typename K>
    struct NonConstTraits {
      typedef K T;
    }
    
    template<typename K>
    struct ConstTraits {
      typedef const K T;
    }
    
    template<typename K>
    struct nonconst_adapter : public arg_adapter<NonConstTraits<K> > {};
    
    template<typename K>
    struct const_adapter : public arg_adapter<ConstTraits<K> > {};
    
    0 讨论(0)
  • 2021-02-08 00:53

    You can make it accept a metafunction and you can apply any transformation you like

    template<template<typename> class F>
    struct arg_adapter
    {
        EArgType type;  // fmtA, fmtB, ...
    
        union
        {
          typename F<TypeA>::type * valueA;
          typename F<TypeB>::type * valueB;
          // ... more types
        };
    
        arg_adapter(typename F<TypeA>::type & value) : type(fmtA), valueA(&value) {}
        arg_adapter(typename F<TypeB>::type & value) : type(fmtB), valueB(&value) {}
        // ...
    };
    
    typename arg_adapter<boost::add_const> const_adapter;
    typename arg_adapter<boost::mpl::identity> nonconst_adapter;
    

    Or accept a metafunction class to get more flexibility (including the ability to make F have default arguments not known to your arg_adapter and such.

    template<typename F>
    struct arg_adapter
    {
        EArgType type;  // fmtA, fmtB, ...
    
        union
        {
          typename apply<F, TypeA>::type * valueA;
          typename apply<F, TypeB>::type * valueB;
          // ... more types
        };
    
        arg_adapter(typename apply<F, TypeA>::type & value) : type(fmtA), valueA(&value) {}
        arg_adapter(typename apply<F, TypeB>::type & value) : type(fmtB), valueB(&value) {}
        // ...
    };
    
    typename arg_adapter< lambda< boost::add_const<_> >::type > const_adapter;
    typename arg_adapter< lambda< boost::mpl::identity<_> >::type > nonconst_adapter;
    
    0 讨论(0)
  • 2021-02-08 01:01

    Maybe I didn't get it, but why can't you use

    Convert(**const** arg_adapter from, arg_adapter to)
    

    Declare a typedef to simplify the job

    0 讨论(0)
提交回复
热议问题