How to compare two typenames for equality in C++?

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











up vote
21
down vote

favorite
8












Suppose I have a template of a function, say



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = GivenFunc1(a, b, single, ...);
...
...



However, for T being a special type, say "SpecialType", I want c being calculated by "GivenFunc2" rather than "GivenFunc1". However, I would not like to write a specialization for "SpecialType", since there will be a huge code duplication. So I want the template function being something like



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = (T == SpecialType) ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
...
...



Of course, this code does not compile since "T == SpecialType" is not valid. So how do I write it in an elegant way?







share|improve this question


















  • 4




    What about writing a template specialization instead of?
    – Ï€Î¬Î½Ï„α ῥεῖ
    Aug 19 at 9:20










  • Possible duplicates: 1 2 3 4
    – user202729
    Aug 20 at 8:33














up vote
21
down vote

favorite
8












Suppose I have a template of a function, say



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = GivenFunc1(a, b, single, ...);
...
...



However, for T being a special type, say "SpecialType", I want c being calculated by "GivenFunc2" rather than "GivenFunc1". However, I would not like to write a specialization for "SpecialType", since there will be a huge code duplication. So I want the template function being something like



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = (T == SpecialType) ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
...
...



Of course, this code does not compile since "T == SpecialType" is not valid. So how do I write it in an elegant way?







share|improve this question


















  • 4




    What about writing a template specialization instead of?
    – Ï€Î¬Î½Ï„α ῥεῖ
    Aug 19 at 9:20










  • Possible duplicates: 1 2 3 4
    – user202729
    Aug 20 at 8:33












up vote
21
down vote

favorite
8









up vote
21
down vote

favorite
8






8





Suppose I have a template of a function, say



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = GivenFunc1(a, b, single, ...);
...
...



However, for T being a special type, say "SpecialType", I want c being calculated by "GivenFunc2" rather than "GivenFunc1". However, I would not like to write a specialization for "SpecialType", since there will be a huge code duplication. So I want the template function being something like



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = (T == SpecialType) ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
...
...



Of course, this code does not compile since "T == SpecialType" is not valid. So how do I write it in an elegant way?







share|improve this question














Suppose I have a template of a function, say



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = GivenFunc1(a, b, single, ...);
...
...



However, for T being a special type, say "SpecialType", I want c being calculated by "GivenFunc2" rather than "GivenFunc1". However, I would not like to write a specialization for "SpecialType", since there will be a huge code duplication. So I want the template function being something like



template<typename T>
func(T a, T b, ...)
...
for (const auto &single : group)
...
auto c = (T == SpecialType) ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);
...
...



Of course, this code does not compile since "T == SpecialType" is not valid. So how do I write it in an elegant way?









share|improve this question













share|improve this question




share|improve this question








edited Aug 20 at 5:00









gyre

10.8k11231




10.8k11231










asked Aug 19 at 9:16









dudulu

1115




1115







  • 4




    What about writing a template specialization instead of?
    – Ï€Î¬Î½Ï„α ῥεῖ
    Aug 19 at 9:20










  • Possible duplicates: 1 2 3 4
    – user202729
    Aug 20 at 8:33












  • 4




    What about writing a template specialization instead of?
    – Ï€Î¬Î½Ï„α ῥεῖ
    Aug 19 at 9:20










  • Possible duplicates: 1 2 3 4
    – user202729
    Aug 20 at 8:33







4




4




What about writing a template specialization instead of?
– Ï€Î¬Î½Ï„α ῥεῖ
Aug 19 at 9:20




What about writing a template specialization instead of?
– Ï€Î¬Î½Ï„α ῥεῖ
Aug 19 at 9:20












Possible duplicates: 1 2 3 4
– user202729
Aug 20 at 8:33




Possible duplicates: 1 2 3 4
– user202729
Aug 20 at 8:33












5 Answers
5






active

oldest

votes

















up vote
28
down vote



accepted










It's as simple as:



auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...)
: GivenFunc1(a, b, single, ...);


If you can't use C++17, replace std::is_same_v<...> with std::is_same<...>::value.



But for this approach to work, both function calls have to be valid for every T you want to use, even if in reality one of them won't be executed.




If it's not the case, you can resort to if constexpr:



your_type_here c;
if constexpr (std::is_same_v<T, SpecialType>)
c = GivenFunc2(a, b, single, ...);
else
c = GivenFunc1(a, b, single, ...);


(This works only in C++17.)






share|improve this answer


















  • 7




    I'd recommend using if constexpr either way. Sure, the compiler should be able to optimise away the check, but checking the validity of the other function call can be costly, especially if it involves additional template instantiations. Also, not using if constexpr can be a maintenance problem for those functions: anyone modifying them will have to take into account that they need to be valid even for arguments for which they'll never be called.
    – hvd
    Aug 19 at 9:29










  • Great answer, lovely 6 votes. Unfortunately, as much as I would like to see this work on the compiler I'm using, it doesn't work. Is this a C++17 template/function?
    – John Law
    Aug 19 at 9:46







  • 3




    @JohnLaw Yes, std::is_same_v is C++17. If you don't have it, use std::is_same<...>::value instead. if constexpr is C++17 too, check other answers for alternatives.
    – HolyBlackCat
    Aug 19 at 9:53










  • Alright, thanks for clarifying. :-)
    – John Law
    Aug 19 at 9:56

















up vote
17
down vote













If you can use C++17, you can achieve the result in a very clean way (with constexpr and is_same):



template<typename T>
func(T a, T b, ...)
// ...

if constexpr (std::is_same_v<T, SpecialType>)
// call GivenFunc2
else
// call GivenFunc1


// ...




Pre C++17 you can achieve the same result using techniques such as SFINAE or "TAG Dispatching".



Additionally, you can just specialize the portion of the code referring to the function call (easy and avoid code duplication).



A short example here:



template <typename T>
struct DispatcherFn
auto operator()(const T&, int)
// call GivenFunc1

;

template <>
struct DispatcherFn<SpecialType>
auto operator()(const SpecialType&, int)
// GivenFunc2

;

template <typename T>
void func(const T& t)
// ... code ...
auto c = DispatcherFn<T>()(t, 49); // specialized call






share|improve this answer





























    up vote
    11
    down vote













    You can always use template specializations instead of doing type comparisons of template parameters. Here's a simplified, working example:



    #include <iostream>
    #include <string>

    template<typename T>
    int GivenFunc1(T a, T b)
    std::cout << "GivenFunc1()" << std::endl;
    return 0;


    template<typename T>
    int GivenFunc2(T a, T b)
    std::cout << "GivenFunc2()" << std::endl;
    return 1;


    template<typename T>
    void func(T a, T b)
    auto c = GivenFunc2(a, b);
    std::cout << c << std::endl;


    template<>
    void func(std::string a, std::string b)
    auto c = GivenFunc1(a, b);
    std::cout << c << std::endl;


    int main()
    func(2,3);
    std::string a = "Hello";
    std::string b = "World";
    func(a,b);



    See it working online here.






    share|improve this answer



























      up vote
      6
      down vote













      In c++17 the best solution is if constexpr.



      In c++14 this works:



      template<class V>
      auto dispatch( V const& )
      return (auto&&...targets)
      return std::get<V>( std::forward_as_tuple( decltype(targets)(targets)... ) );
      ;



      then:



       auto c = dispatch( std::is_same<T, SpecialType> )
      (
      [&](auto&& a, auto&& b) return GivenFunc2(a, b, single...); ,
      [&](auto&& a, auto&& b) return GivenFunc1(a, b, single, ...);
      )( a, b );


      does what you want. (It is also a function which returns a function which returns a function)



      Live example.



      dispatch picks one of the two lambdas and returns it at compile time. We then call the picked lambda with a and b. So only the valid one is compiled with a type for a and b.






      share|improve this answer





























        up vote
        1
        down vote













        Convert GivenFunc1 to a functor and specialise that.



        template <class T>
        class GivenFunc

        X operator()(T a, T b, Y single)

        ...



        template <>
        class GivenFunc<SpecialType>

        X operator()(SpecialType a, SpecialType b, Y single)

        ...




        Then you can say



        auto c = GivenFunc<T>()(a, b, single);





        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%2f51916198%2fhow-to-compare-two-typenames-for-equality-in-c%23new-answer', 'question_page');

          );

          Post as a guest






























          5 Answers
          5






          active

          oldest

          votes








          5 Answers
          5






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          up vote
          28
          down vote



          accepted










          It's as simple as:



          auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...)
          : GivenFunc1(a, b, single, ...);


          If you can't use C++17, replace std::is_same_v<...> with std::is_same<...>::value.



          But for this approach to work, both function calls have to be valid for every T you want to use, even if in reality one of them won't be executed.




          If it's not the case, you can resort to if constexpr:



          your_type_here c;
          if constexpr (std::is_same_v<T, SpecialType>)
          c = GivenFunc2(a, b, single, ...);
          else
          c = GivenFunc1(a, b, single, ...);


          (This works only in C++17.)






          share|improve this answer


















          • 7




            I'd recommend using if constexpr either way. Sure, the compiler should be able to optimise away the check, but checking the validity of the other function call can be costly, especially if it involves additional template instantiations. Also, not using if constexpr can be a maintenance problem for those functions: anyone modifying them will have to take into account that they need to be valid even for arguments for which they'll never be called.
            – hvd
            Aug 19 at 9:29










          • Great answer, lovely 6 votes. Unfortunately, as much as I would like to see this work on the compiler I'm using, it doesn't work. Is this a C++17 template/function?
            – John Law
            Aug 19 at 9:46







          • 3




            @JohnLaw Yes, std::is_same_v is C++17. If you don't have it, use std::is_same<...>::value instead. if constexpr is C++17 too, check other answers for alternatives.
            – HolyBlackCat
            Aug 19 at 9:53










          • Alright, thanks for clarifying. :-)
            – John Law
            Aug 19 at 9:56














          up vote
          28
          down vote



          accepted










          It's as simple as:



          auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...)
          : GivenFunc1(a, b, single, ...);


          If you can't use C++17, replace std::is_same_v<...> with std::is_same<...>::value.



          But for this approach to work, both function calls have to be valid for every T you want to use, even if in reality one of them won't be executed.




          If it's not the case, you can resort to if constexpr:



          your_type_here c;
          if constexpr (std::is_same_v<T, SpecialType>)
          c = GivenFunc2(a, b, single, ...);
          else
          c = GivenFunc1(a, b, single, ...);


          (This works only in C++17.)






          share|improve this answer


















          • 7




            I'd recommend using if constexpr either way. Sure, the compiler should be able to optimise away the check, but checking the validity of the other function call can be costly, especially if it involves additional template instantiations. Also, not using if constexpr can be a maintenance problem for those functions: anyone modifying them will have to take into account that they need to be valid even for arguments for which they'll never be called.
            – hvd
            Aug 19 at 9:29










          • Great answer, lovely 6 votes. Unfortunately, as much as I would like to see this work on the compiler I'm using, it doesn't work. Is this a C++17 template/function?
            – John Law
            Aug 19 at 9:46







          • 3




            @JohnLaw Yes, std::is_same_v is C++17. If you don't have it, use std::is_same<...>::value instead. if constexpr is C++17 too, check other answers for alternatives.
            – HolyBlackCat
            Aug 19 at 9:53










          • Alright, thanks for clarifying. :-)
            – John Law
            Aug 19 at 9:56












          up vote
          28
          down vote



          accepted







          up vote
          28
          down vote



          accepted






          It's as simple as:



          auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...)
          : GivenFunc1(a, b, single, ...);


          If you can't use C++17, replace std::is_same_v<...> with std::is_same<...>::value.



          But for this approach to work, both function calls have to be valid for every T you want to use, even if in reality one of them won't be executed.




          If it's not the case, you can resort to if constexpr:



          your_type_here c;
          if constexpr (std::is_same_v<T, SpecialType>)
          c = GivenFunc2(a, b, single, ...);
          else
          c = GivenFunc1(a, b, single, ...);


          (This works only in C++17.)






          share|improve this answer














          It's as simple as:



          auto c = std::is_same_v<T, SpecialType> ? GivenFunc2(a, b, single, ...)
          : GivenFunc1(a, b, single, ...);


          If you can't use C++17, replace std::is_same_v<...> with std::is_same<...>::value.



          But for this approach to work, both function calls have to be valid for every T you want to use, even if in reality one of them won't be executed.




          If it's not the case, you can resort to if constexpr:



          your_type_here c;
          if constexpr (std::is_same_v<T, SpecialType>)
          c = GivenFunc2(a, b, single, ...);
          else
          c = GivenFunc1(a, b, single, ...);


          (This works only in C++17.)







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Aug 20 at 9:52









          Toby Speight

          14.9k133761




          14.9k133761










          answered Aug 19 at 9:24









          HolyBlackCat

          13.7k23357




          13.7k23357







          • 7




            I'd recommend using if constexpr either way. Sure, the compiler should be able to optimise away the check, but checking the validity of the other function call can be costly, especially if it involves additional template instantiations. Also, not using if constexpr can be a maintenance problem for those functions: anyone modifying them will have to take into account that they need to be valid even for arguments for which they'll never be called.
            – hvd
            Aug 19 at 9:29










          • Great answer, lovely 6 votes. Unfortunately, as much as I would like to see this work on the compiler I'm using, it doesn't work. Is this a C++17 template/function?
            – John Law
            Aug 19 at 9:46







          • 3




            @JohnLaw Yes, std::is_same_v is C++17. If you don't have it, use std::is_same<...>::value instead. if constexpr is C++17 too, check other answers for alternatives.
            – HolyBlackCat
            Aug 19 at 9:53










          • Alright, thanks for clarifying. :-)
            – John Law
            Aug 19 at 9:56












          • 7




            I'd recommend using if constexpr either way. Sure, the compiler should be able to optimise away the check, but checking the validity of the other function call can be costly, especially if it involves additional template instantiations. Also, not using if constexpr can be a maintenance problem for those functions: anyone modifying them will have to take into account that they need to be valid even for arguments for which they'll never be called.
            – hvd
            Aug 19 at 9:29










          • Great answer, lovely 6 votes. Unfortunately, as much as I would like to see this work on the compiler I'm using, it doesn't work. Is this a C++17 template/function?
            – John Law
            Aug 19 at 9:46







          • 3




            @JohnLaw Yes, std::is_same_v is C++17. If you don't have it, use std::is_same<...>::value instead. if constexpr is C++17 too, check other answers for alternatives.
            – HolyBlackCat
            Aug 19 at 9:53










          • Alright, thanks for clarifying. :-)
            – John Law
            Aug 19 at 9:56







          7




          7




          I'd recommend using if constexpr either way. Sure, the compiler should be able to optimise away the check, but checking the validity of the other function call can be costly, especially if it involves additional template instantiations. Also, not using if constexpr can be a maintenance problem for those functions: anyone modifying them will have to take into account that they need to be valid even for arguments for which they'll never be called.
          – hvd
          Aug 19 at 9:29




          I'd recommend using if constexpr either way. Sure, the compiler should be able to optimise away the check, but checking the validity of the other function call can be costly, especially if it involves additional template instantiations. Also, not using if constexpr can be a maintenance problem for those functions: anyone modifying them will have to take into account that they need to be valid even for arguments for which they'll never be called.
          – hvd
          Aug 19 at 9:29












          Great answer, lovely 6 votes. Unfortunately, as much as I would like to see this work on the compiler I'm using, it doesn't work. Is this a C++17 template/function?
          – John Law
          Aug 19 at 9:46





          Great answer, lovely 6 votes. Unfortunately, as much as I would like to see this work on the compiler I'm using, it doesn't work. Is this a C++17 template/function?
          – John Law
          Aug 19 at 9:46





          3




          3




          @JohnLaw Yes, std::is_same_v is C++17. If you don't have it, use std::is_same<...>::value instead. if constexpr is C++17 too, check other answers for alternatives.
          – HolyBlackCat
          Aug 19 at 9:53




          @JohnLaw Yes, std::is_same_v is C++17. If you don't have it, use std::is_same<...>::value instead. if constexpr is C++17 too, check other answers for alternatives.
          – HolyBlackCat
          Aug 19 at 9:53












          Alright, thanks for clarifying. :-)
          – John Law
          Aug 19 at 9:56




          Alright, thanks for clarifying. :-)
          – John Law
          Aug 19 at 9:56












          up vote
          17
          down vote













          If you can use C++17, you can achieve the result in a very clean way (with constexpr and is_same):



          template<typename T>
          func(T a, T b, ...)
          // ...

          if constexpr (std::is_same_v<T, SpecialType>)
          // call GivenFunc2
          else
          // call GivenFunc1


          // ...




          Pre C++17 you can achieve the same result using techniques such as SFINAE or "TAG Dispatching".



          Additionally, you can just specialize the portion of the code referring to the function call (easy and avoid code duplication).



          A short example here:



          template <typename T>
          struct DispatcherFn
          auto operator()(const T&, int)
          // call GivenFunc1

          ;

          template <>
          struct DispatcherFn<SpecialType>
          auto operator()(const SpecialType&, int)
          // GivenFunc2

          ;

          template <typename T>
          void func(const T& t)
          // ... code ...
          auto c = DispatcherFn<T>()(t, 49); // specialized call






          share|improve this answer


























            up vote
            17
            down vote













            If you can use C++17, you can achieve the result in a very clean way (with constexpr and is_same):



            template<typename T>
            func(T a, T b, ...)
            // ...

            if constexpr (std::is_same_v<T, SpecialType>)
            // call GivenFunc2
            else
            // call GivenFunc1


            // ...




            Pre C++17 you can achieve the same result using techniques such as SFINAE or "TAG Dispatching".



            Additionally, you can just specialize the portion of the code referring to the function call (easy and avoid code duplication).



            A short example here:



            template <typename T>
            struct DispatcherFn
            auto operator()(const T&, int)
            // call GivenFunc1

            ;

            template <>
            struct DispatcherFn<SpecialType>
            auto operator()(const SpecialType&, int)
            // GivenFunc2

            ;

            template <typename T>
            void func(const T& t)
            // ... code ...
            auto c = DispatcherFn<T>()(t, 49); // specialized call






            share|improve this answer
























              up vote
              17
              down vote










              up vote
              17
              down vote









              If you can use C++17, you can achieve the result in a very clean way (with constexpr and is_same):



              template<typename T>
              func(T a, T b, ...)
              // ...

              if constexpr (std::is_same_v<T, SpecialType>)
              // call GivenFunc2
              else
              // call GivenFunc1


              // ...




              Pre C++17 you can achieve the same result using techniques such as SFINAE or "TAG Dispatching".



              Additionally, you can just specialize the portion of the code referring to the function call (easy and avoid code duplication).



              A short example here:



              template <typename T>
              struct DispatcherFn
              auto operator()(const T&, int)
              // call GivenFunc1

              ;

              template <>
              struct DispatcherFn<SpecialType>
              auto operator()(const SpecialType&, int)
              // GivenFunc2

              ;

              template <typename T>
              void func(const T& t)
              // ... code ...
              auto c = DispatcherFn<T>()(t, 49); // specialized call






              share|improve this answer














              If you can use C++17, you can achieve the result in a very clean way (with constexpr and is_same):



              template<typename T>
              func(T a, T b, ...)
              // ...

              if constexpr (std::is_same_v<T, SpecialType>)
              // call GivenFunc2
              else
              // call GivenFunc1


              // ...




              Pre C++17 you can achieve the same result using techniques such as SFINAE or "TAG Dispatching".



              Additionally, you can just specialize the portion of the code referring to the function call (easy and avoid code duplication).



              A short example here:



              template <typename T>
              struct DispatcherFn
              auto operator()(const T&, int)
              // call GivenFunc1

              ;

              template <>
              struct DispatcherFn<SpecialType>
              auto operator()(const SpecialType&, int)
              // GivenFunc2

              ;

              template <typename T>
              void func(const T& t)
              // ... code ...
              auto c = DispatcherFn<T>()(t, 49); // specialized call







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Aug 20 at 0:38

























              answered Aug 19 at 9:30









              Biagio Festa

              4,53121035




              4,53121035




















                  up vote
                  11
                  down vote













                  You can always use template specializations instead of doing type comparisons of template parameters. Here's a simplified, working example:



                  #include <iostream>
                  #include <string>

                  template<typename T>
                  int GivenFunc1(T a, T b)
                  std::cout << "GivenFunc1()" << std::endl;
                  return 0;


                  template<typename T>
                  int GivenFunc2(T a, T b)
                  std::cout << "GivenFunc2()" << std::endl;
                  return 1;


                  template<typename T>
                  void func(T a, T b)
                  auto c = GivenFunc2(a, b);
                  std::cout << c << std::endl;


                  template<>
                  void func(std::string a, std::string b)
                  auto c = GivenFunc1(a, b);
                  std::cout << c << std::endl;


                  int main()
                  func(2,3);
                  std::string a = "Hello";
                  std::string b = "World";
                  func(a,b);



                  See it working online here.






                  share|improve this answer
























                    up vote
                    11
                    down vote













                    You can always use template specializations instead of doing type comparisons of template parameters. Here's a simplified, working example:



                    #include <iostream>
                    #include <string>

                    template<typename T>
                    int GivenFunc1(T a, T b)
                    std::cout << "GivenFunc1()" << std::endl;
                    return 0;


                    template<typename T>
                    int GivenFunc2(T a, T b)
                    std::cout << "GivenFunc2()" << std::endl;
                    return 1;


                    template<typename T>
                    void func(T a, T b)
                    auto c = GivenFunc2(a, b);
                    std::cout << c << std::endl;


                    template<>
                    void func(std::string a, std::string b)
                    auto c = GivenFunc1(a, b);
                    std::cout << c << std::endl;


                    int main()
                    func(2,3);
                    std::string a = "Hello";
                    std::string b = "World";
                    func(a,b);



                    See it working online here.






                    share|improve this answer






















                      up vote
                      11
                      down vote










                      up vote
                      11
                      down vote









                      You can always use template specializations instead of doing type comparisons of template parameters. Here's a simplified, working example:



                      #include <iostream>
                      #include <string>

                      template<typename T>
                      int GivenFunc1(T a, T b)
                      std::cout << "GivenFunc1()" << std::endl;
                      return 0;


                      template<typename T>
                      int GivenFunc2(T a, T b)
                      std::cout << "GivenFunc2()" << std::endl;
                      return 1;


                      template<typename T>
                      void func(T a, T b)
                      auto c = GivenFunc2(a, b);
                      std::cout << c << std::endl;


                      template<>
                      void func(std::string a, std::string b)
                      auto c = GivenFunc1(a, b);
                      std::cout << c << std::endl;


                      int main()
                      func(2,3);
                      std::string a = "Hello";
                      std::string b = "World";
                      func(a,b);



                      See it working online here.






                      share|improve this answer












                      You can always use template specializations instead of doing type comparisons of template parameters. Here's a simplified, working example:



                      #include <iostream>
                      #include <string>

                      template<typename T>
                      int GivenFunc1(T a, T b)
                      std::cout << "GivenFunc1()" << std::endl;
                      return 0;


                      template<typename T>
                      int GivenFunc2(T a, T b)
                      std::cout << "GivenFunc2()" << std::endl;
                      return 1;


                      template<typename T>
                      void func(T a, T b)
                      auto c = GivenFunc2(a, b);
                      std::cout << c << std::endl;


                      template<>
                      void func(std::string a, std::string b)
                      auto c = GivenFunc1(a, b);
                      std::cout << c << std::endl;


                      int main()
                      func(2,3);
                      std::string a = "Hello";
                      std::string b = "World";
                      func(a,b);



                      See it working online here.







                      share|improve this answer












                      share|improve this answer



                      share|improve this answer










                      answered Aug 19 at 9:35









                      πάντα ῥεῖ

                      70k869132




                      70k869132




















                          up vote
                          6
                          down vote













                          In c++17 the best solution is if constexpr.



                          In c++14 this works:



                          template<class V>
                          auto dispatch( V const& )
                          return (auto&&...targets)
                          return std::get<V>( std::forward_as_tuple( decltype(targets)(targets)... ) );
                          ;



                          then:



                           auto c = dispatch( std::is_same<T, SpecialType> )
                          (
                          [&](auto&& a, auto&& b) return GivenFunc2(a, b, single...); ,
                          [&](auto&& a, auto&& b) return GivenFunc1(a, b, single, ...);
                          )( a, b );


                          does what you want. (It is also a function which returns a function which returns a function)



                          Live example.



                          dispatch picks one of the two lambdas and returns it at compile time. We then call the picked lambda with a and b. So only the valid one is compiled with a type for a and b.






                          share|improve this answer


























                            up vote
                            6
                            down vote













                            In c++17 the best solution is if constexpr.



                            In c++14 this works:



                            template<class V>
                            auto dispatch( V const& )
                            return (auto&&...targets)
                            return std::get<V>( std::forward_as_tuple( decltype(targets)(targets)... ) );
                            ;



                            then:



                             auto c = dispatch( std::is_same<T, SpecialType> )
                            (
                            [&](auto&& a, auto&& b) return GivenFunc2(a, b, single...); ,
                            [&](auto&& a, auto&& b) return GivenFunc1(a, b, single, ...);
                            )( a, b );


                            does what you want. (It is also a function which returns a function which returns a function)



                            Live example.



                            dispatch picks one of the two lambdas and returns it at compile time. We then call the picked lambda with a and b. So only the valid one is compiled with a type for a and b.






                            share|improve this answer
























                              up vote
                              6
                              down vote










                              up vote
                              6
                              down vote









                              In c++17 the best solution is if constexpr.



                              In c++14 this works:



                              template<class V>
                              auto dispatch( V const& )
                              return (auto&&...targets)
                              return std::get<V>( std::forward_as_tuple( decltype(targets)(targets)... ) );
                              ;



                              then:



                               auto c = dispatch( std::is_same<T, SpecialType> )
                              (
                              [&](auto&& a, auto&& b) return GivenFunc2(a, b, single...); ,
                              [&](auto&& a, auto&& b) return GivenFunc1(a, b, single, ...);
                              )( a, b );


                              does what you want. (It is also a function which returns a function which returns a function)



                              Live example.



                              dispatch picks one of the two lambdas and returns it at compile time. We then call the picked lambda with a and b. So only the valid one is compiled with a type for a and b.






                              share|improve this answer














                              In c++17 the best solution is if constexpr.



                              In c++14 this works:



                              template<class V>
                              auto dispatch( V const& )
                              return (auto&&...targets)
                              return std::get<V>( std::forward_as_tuple( decltype(targets)(targets)... ) );
                              ;



                              then:



                               auto c = dispatch( std::is_same<T, SpecialType> )
                              (
                              [&](auto&& a, auto&& b) return GivenFunc2(a, b, single...); ,
                              [&](auto&& a, auto&& b) return GivenFunc1(a, b, single, ...);
                              )( a, b );


                              does what you want. (It is also a function which returns a function which returns a function)



                              Live example.



                              dispatch picks one of the two lambdas and returns it at compile time. We then call the picked lambda with a and b. So only the valid one is compiled with a type for a and b.







                              share|improve this answer














                              share|improve this answer



                              share|improve this answer








                              edited Aug 20 at 19:41

























                              answered Aug 19 at 11:21









                              Yakk - Adam Nevraumont

                              169k18172349




                              169k18172349




















                                  up vote
                                  1
                                  down vote













                                  Convert GivenFunc1 to a functor and specialise that.



                                  template <class T>
                                  class GivenFunc

                                  X operator()(T a, T b, Y single)

                                  ...



                                  template <>
                                  class GivenFunc<SpecialType>

                                  X operator()(SpecialType a, SpecialType b, Y single)

                                  ...




                                  Then you can say



                                  auto c = GivenFunc<T>()(a, b, single);





                                  share|improve this answer
























                                    up vote
                                    1
                                    down vote













                                    Convert GivenFunc1 to a functor and specialise that.



                                    template <class T>
                                    class GivenFunc

                                    X operator()(T a, T b, Y single)

                                    ...



                                    template <>
                                    class GivenFunc<SpecialType>

                                    X operator()(SpecialType a, SpecialType b, Y single)

                                    ...




                                    Then you can say



                                    auto c = GivenFunc<T>()(a, b, single);





                                    share|improve this answer






















                                      up vote
                                      1
                                      down vote










                                      up vote
                                      1
                                      down vote









                                      Convert GivenFunc1 to a functor and specialise that.



                                      template <class T>
                                      class GivenFunc

                                      X operator()(T a, T b, Y single)

                                      ...



                                      template <>
                                      class GivenFunc<SpecialType>

                                      X operator()(SpecialType a, SpecialType b, Y single)

                                      ...




                                      Then you can say



                                      auto c = GivenFunc<T>()(a, b, single);





                                      share|improve this answer












                                      Convert GivenFunc1 to a functor and specialise that.



                                      template <class T>
                                      class GivenFunc

                                      X operator()(T a, T b, Y single)

                                      ...



                                      template <>
                                      class GivenFunc<SpecialType>

                                      X operator()(SpecialType a, SpecialType b, Y single)

                                      ...




                                      Then you can say



                                      auto c = GivenFunc<T>()(a, b, single);






                                      share|improve this answer












                                      share|improve this answer



                                      share|improve this answer










                                      answered Aug 19 at 9:30









                                      john

                                      32.8k12645




                                      32.8k12645



























                                           

                                          draft saved


                                          draft discarded















































                                           


                                          draft saved


                                          draft discarded














                                          StackExchange.ready(
                                          function ()
                                          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51916198%2fhow-to-compare-two-typenames-for-equality-in-c%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