Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
585 views
in Technique[技术] by (71.8m points)

c++17 - How to add member function of template class only on specific types using type_traits | C++

template <typename T>
class A
{
        template <std::enable_if_t<std::is_signed_v<T>, bool> = true>
        constexpr value_type determinant()
        {
            
        }
}

I wanna determinant function is instantiated only when type T is signed type so I try this codes, but when type T is unsigned compiler still try instantiate determinant function.

I don't wanna specialize template function about each signed type T.
I want to use std::is_signed_v type traits to simplify codes

question from:https://stackoverflow.com/questions/65922386/how-to-add-member-function-of-template-class-only-on-specific-types-using-type-t

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

With SFINAE you can enable/disable a method of a class when the condition tested is related to a template parameter of the method itself. Doesn't works testing a template parameter of the class.

You can solve the problem passing through a method template parameter that is defaulted with the type of the class/struct template parameter.

For example

#include <iostream>
#include <type_traits>

template <typename T>
struct foo
 {
   template <typename U = T,
             std::enable_if_t<std::is_signed_v<U>, bool> = true>
   constexpr std::size_t bar ()
    { return sizeof(T); }
 };

int main() 
 {
   foo<signed int>   fs;
   foo<unsigned int> fu;

   fs.bar(); // compile
   //fu.bar(); // compilation error
 }

The problem of this solution is that you can "hijack" it explicating a template parameter

fu.bar(); // compilation error
fu.bar<int>(); // compile 

To avoid the hijacking risk, you can (other solutions are possible but this is my preferred) add a non-type variadic template parameter before U

// .......VVVVVVVV  add this to avoid the hijacking problem
template <int ...,
          typename U = T,
          std::enable_if_t<std::is_signed_v<U>, bool> = true>
constexpr std::size_t bar ()
 { return sizeof(T); }

// ...

fu.bar(); // compilation error
fu.bar<int>(); // compilation error
fu.bar<1, 2, 3, int>(); // compilation error

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...