Add const to type if template arg is const

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
8
down vote

favorite
2












I have a class:



struct Foo 
vector<float> data;
;


and I have a templated function that takes a Foo&:



template<typename T>
void f(T& arg)
using ftype = float *; // <-- would like this to be const float * if T is const
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...



How can I make ptr be const float * iff T is const? I know about add_const and is_const but don't see how to use them here. (My real struct is more complicated and I don't have direct access to its internals; it's actually an OpenCV cv::Mat.)
I can use recent (C++14/C++17) features if needed.



I'll use it like this:



Foo foo1 = Foo();
f(foo1); // modifiable in f
const Foo cfoo = Foo();
f(cfoo); // const, should not be modifiable in f









share|improve this question



















  • 4




    If you wrote auto ptr = &arg.data[0];, decltype(ptr) would be const float*, no type traits needed
    – Justin
    6 hours ago














up vote
8
down vote

favorite
2












I have a class:



struct Foo 
vector<float> data;
;


and I have a templated function that takes a Foo&:



template<typename T>
void f(T& arg)
using ftype = float *; // <-- would like this to be const float * if T is const
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...



How can I make ptr be const float * iff T is const? I know about add_const and is_const but don't see how to use them here. (My real struct is more complicated and I don't have direct access to its internals; it's actually an OpenCV cv::Mat.)
I can use recent (C++14/C++17) features if needed.



I'll use it like this:



Foo foo1 = Foo();
f(foo1); // modifiable in f
const Foo cfoo = Foo();
f(cfoo); // const, should not be modifiable in f









share|improve this question



















  • 4




    If you wrote auto ptr = &arg.data[0];, decltype(ptr) would be const float*, no type traits needed
    – Justin
    6 hours ago












up vote
8
down vote

favorite
2









up vote
8
down vote

favorite
2






2





I have a class:



struct Foo 
vector<float> data;
;


and I have a templated function that takes a Foo&:



template<typename T>
void f(T& arg)
using ftype = float *; // <-- would like this to be const float * if T is const
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...



How can I make ptr be const float * iff T is const? I know about add_const and is_const but don't see how to use them here. (My real struct is more complicated and I don't have direct access to its internals; it's actually an OpenCV cv::Mat.)
I can use recent (C++14/C++17) features if needed.



I'll use it like this:



Foo foo1 = Foo();
f(foo1); // modifiable in f
const Foo cfoo = Foo();
f(cfoo); // const, should not be modifiable in f









share|improve this question















I have a class:



struct Foo 
vector<float> data;
;


and I have a templated function that takes a Foo&:



template<typename T>
void f(T& arg)
using ftype = float *; // <-- would like this to be const float * if T is const
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...



How can I make ptr be const float * iff T is const? I know about add_const and is_const but don't see how to use them here. (My real struct is more complicated and I don't have direct access to its internals; it's actually an OpenCV cv::Mat.)
I can use recent (C++14/C++17) features if needed.



I'll use it like this:



Foo foo1 = Foo();
f(foo1); // modifiable in f
const Foo cfoo = Foo();
f(cfoo); // const, should not be modifiable in f






c++ c++11 templates






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 12 mins ago









Konrad Rudolph

386k1007601011




386k1007601011










asked 6 hours ago









GaryO

1,325915




1,325915







  • 4




    If you wrote auto ptr = &arg.data[0];, decltype(ptr) would be const float*, no type traits needed
    – Justin
    6 hours ago












  • 4




    If you wrote auto ptr = &arg.data[0];, decltype(ptr) would be const float*, no type traits needed
    – Justin
    6 hours ago







4




4




If you wrote auto ptr = &arg.data[0];, decltype(ptr) would be const float*, no type traits needed
– Justin
6 hours ago




If you wrote auto ptr = &arg.data[0];, decltype(ptr) would be const float*, no type traits needed
– Justin
6 hours ago












2 Answers
2






active

oldest

votes

















up vote
10
down vote



accepted










Most likely, you actually just want the type of the expression &arg.data[0], for which you can use decltype.



You can also use std::conditional to distinguish the cases.



template<typename T>
void f(T& arg)
// C++17: using ftype = std::conditional_t<std::is_const_v<T>, const float *, float *>;
using ftype = typename std::conditional<std::is_const<T>::value, const float *, float *>::type;

ftype ptr = &arg.data[0];
// ... do stuff with ptr ...



If instead of float *, you had a second type parameter U, you would include std::add_const



template<typename T, typename U = float *>
void f(T& arg)
// C++17: using ftype = std::conditional_t<std::is_const_v<T>, std::add_const_t<U>, U>;
using ftype = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
// ... do stuff with ftype ...



I have marked where C++14 and C++17 has nicer syntax for equivalent use. C++11 lack of template usings and template variables results in verbose type functions :(.






share|improve this answer


















  • 2




    The big win is for C++14: _t versus typename ::value. C++17 is only ::value vs _v.
    – Jarod42
    5 hours ago

















up vote
3
down vote













template<class Src, class Dst>
using transcribe_const_t = std::conditional_t<std::is_const<Src>, Dst const, Dst>;
template<class Src, class Dst>
using transcribe_volatile_t = std::conditional_t<std::is_volatile<Src>, Dst volatile, Dst>;
template<class Src, class Dst>
using transcribe_cv_t = transcribe_const_t< Src, transcribe_volatile_t< Src, Dst> >;


now



template<typename T>
void f(T& arg)
using ftype = transcribe_cv_t<T, float>*;
ftype ptr = &arg.data[0];
// ... do stuff with ptr ...



does what you ask (and a bit more).






share|improve this answer






















    Your Answer





    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "1"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: true,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );













     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52559336%2fadd-const-to-type-if-template-arg-is-const%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    10
    down vote



    accepted










    Most likely, you actually just want the type of the expression &arg.data[0], for which you can use decltype.



    You can also use std::conditional to distinguish the cases.



    template<typename T>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, const float *, float *>;
    using ftype = typename std::conditional<std::is_const<T>::value, const float *, float *>::type;

    ftype ptr = &arg.data[0];
    // ... do stuff with ptr ...



    If instead of float *, you had a second type parameter U, you would include std::add_const



    template<typename T, typename U = float *>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, std::add_const_t<U>, U>;
    using ftype = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
    // ... do stuff with ftype ...



    I have marked where C++14 and C++17 has nicer syntax for equivalent use. C++11 lack of template usings and template variables results in verbose type functions :(.






    share|improve this answer


















    • 2




      The big win is for C++14: _t versus typename ::value. C++17 is only ::value vs _v.
      – Jarod42
      5 hours ago














    up vote
    10
    down vote



    accepted










    Most likely, you actually just want the type of the expression &arg.data[0], for which you can use decltype.



    You can also use std::conditional to distinguish the cases.



    template<typename T>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, const float *, float *>;
    using ftype = typename std::conditional<std::is_const<T>::value, const float *, float *>::type;

    ftype ptr = &arg.data[0];
    // ... do stuff with ptr ...



    If instead of float *, you had a second type parameter U, you would include std::add_const



    template<typename T, typename U = float *>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, std::add_const_t<U>, U>;
    using ftype = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
    // ... do stuff with ftype ...



    I have marked where C++14 and C++17 has nicer syntax for equivalent use. C++11 lack of template usings and template variables results in verbose type functions :(.






    share|improve this answer


















    • 2




      The big win is for C++14: _t versus typename ::value. C++17 is only ::value vs _v.
      – Jarod42
      5 hours ago












    up vote
    10
    down vote



    accepted







    up vote
    10
    down vote



    accepted






    Most likely, you actually just want the type of the expression &arg.data[0], for which you can use decltype.



    You can also use std::conditional to distinguish the cases.



    template<typename T>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, const float *, float *>;
    using ftype = typename std::conditional<std::is_const<T>::value, const float *, float *>::type;

    ftype ptr = &arg.data[0];
    // ... do stuff with ptr ...



    If instead of float *, you had a second type parameter U, you would include std::add_const



    template<typename T, typename U = float *>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, std::add_const_t<U>, U>;
    using ftype = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
    // ... do stuff with ftype ...



    I have marked where C++14 and C++17 has nicer syntax for equivalent use. C++11 lack of template usings and template variables results in verbose type functions :(.






    share|improve this answer














    Most likely, you actually just want the type of the expression &arg.data[0], for which you can use decltype.



    You can also use std::conditional to distinguish the cases.



    template<typename T>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, const float *, float *>;
    using ftype = typename std::conditional<std::is_const<T>::value, const float *, float *>::type;

    ftype ptr = &arg.data[0];
    // ... do stuff with ptr ...



    If instead of float *, you had a second type parameter U, you would include std::add_const



    template<typename T, typename U = float *>
    void f(T& arg)
    // C++17: using ftype = std::conditional_t<std::is_const_v<T>, std::add_const_t<U>, U>;
    using ftype = typename std::conditional<std::is_const<T>::value, typename std::add_const<U>::type, U>::type;
    // ... do stuff with ftype ...



    I have marked where C++14 and C++17 has nicer syntax for equivalent use. C++11 lack of template usings and template variables results in verbose type functions :(.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 3 hours ago

























    answered 6 hours ago









    Caleth

    12.8k11432




    12.8k11432







    • 2




      The big win is for C++14: _t versus typename ::value. C++17 is only ::value vs _v.
      – Jarod42
      5 hours ago












    • 2




      The big win is for C++14: _t versus typename ::value. C++17 is only ::value vs _v.
      – Jarod42
      5 hours ago







    2




    2




    The big win is for C++14: _t versus typename ::value. C++17 is only ::value vs _v.
    – Jarod42
    5 hours ago




    The big win is for C++14: _t versus typename ::value. C++17 is only ::value vs _v.
    – Jarod42
    5 hours ago












    up vote
    3
    down vote













    template<class Src, class Dst>
    using transcribe_const_t = std::conditional_t<std::is_const<Src>, Dst const, Dst>;
    template<class Src, class Dst>
    using transcribe_volatile_t = std::conditional_t<std::is_volatile<Src>, Dst volatile, Dst>;
    template<class Src, class Dst>
    using transcribe_cv_t = transcribe_const_t< Src, transcribe_volatile_t< Src, Dst> >;


    now



    template<typename T>
    void f(T& arg)
    using ftype = transcribe_cv_t<T, float>*;
    ftype ptr = &arg.data[0];
    // ... do stuff with ptr ...



    does what you ask (and a bit more).






    share|improve this answer


























      up vote
      3
      down vote













      template<class Src, class Dst>
      using transcribe_const_t = std::conditional_t<std::is_const<Src>, Dst const, Dst>;
      template<class Src, class Dst>
      using transcribe_volatile_t = std::conditional_t<std::is_volatile<Src>, Dst volatile, Dst>;
      template<class Src, class Dst>
      using transcribe_cv_t = transcribe_const_t< Src, transcribe_volatile_t< Src, Dst> >;


      now



      template<typename T>
      void f(T& arg)
      using ftype = transcribe_cv_t<T, float>*;
      ftype ptr = &arg.data[0];
      // ... do stuff with ptr ...



      does what you ask (and a bit more).






      share|improve this answer
























        up vote
        3
        down vote










        up vote
        3
        down vote









        template<class Src, class Dst>
        using transcribe_const_t = std::conditional_t<std::is_const<Src>, Dst const, Dst>;
        template<class Src, class Dst>
        using transcribe_volatile_t = std::conditional_t<std::is_volatile<Src>, Dst volatile, Dst>;
        template<class Src, class Dst>
        using transcribe_cv_t = transcribe_const_t< Src, transcribe_volatile_t< Src, Dst> >;


        now



        template<typename T>
        void f(T& arg)
        using ftype = transcribe_cv_t<T, float>*;
        ftype ptr = &arg.data[0];
        // ... do stuff with ptr ...



        does what you ask (and a bit more).






        share|improve this answer














        template<class Src, class Dst>
        using transcribe_const_t = std::conditional_t<std::is_const<Src>, Dst const, Dst>;
        template<class Src, class Dst>
        using transcribe_volatile_t = std::conditional_t<std::is_volatile<Src>, Dst volatile, Dst>;
        template<class Src, class Dst>
        using transcribe_cv_t = transcribe_const_t< Src, transcribe_volatile_t< Src, Dst> >;


        now



        template<typename T>
        void f(T& arg)
        using ftype = transcribe_cv_t<T, float>*;
        ftype ptr = &arg.data[0];
        // ... do stuff with ptr ...



        does what you ask (and a bit more).







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited 3 hours ago









        Jarod42

        108k1297172




        108k1297172










        answered 5 hours ago









        Yakk - Adam Nevraumont

        171k18175353




        171k18175353



























             

            draft saved


            draft discarded















































             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52559336%2fadd-const-to-type-if-template-arg-is-const%23new-answer', 'question_page');

            );

            Post as a guest













































































            Comments

            Popular posts from this blog

            Long meetings (6-7 hours a day): Being “babysat” by supervisor

            Is the Concept of Multiple Fantasy Races Scientifically Flawed? [closed]

            Confectionery