C++模板部分特化 - 最专用于unique_ptr <t>

Are*_*ius 6 c++ templates sfinae template-specialization c++11

我正在尝试创建部分专用模板,如果传递了一个,则进一步专门化 std::unique_ptr

template <typename T, typename = void>
struct Foo;

// A
template <typename T>
struct Foo<std::unique_ptr<T>, typename std::enable_if<std::is_class<T>::value>::type> {...};

// B
template <typename T>
struct Foo<T, typename std::enable_if<std::is_class<T>::value>::type> {...};

void fn() {
    Foo<std::unique_ptr<T>> foo;
}
Run Code Online (Sandbox Code Playgroud)

我的理解是A比B更专业,应该是使用的.但至少在MSVC 2015中我得到了错误:

error C2752: 'Foo<FieldT,void>': more than one partial specialization matches the template argument list
Run Code Online (Sandbox Code Playgroud)

这里有什么我想念的吗?

max*_*x66 5

问题:应该使用哪个专业名称进行呼叫foo<std::unique_ptr<int>>

请注意,这int不是类,因此值std::is_class<T>::value是false,A版本不匹配。

如果要A在第一个模板参数为时使用该版本,则std::unique_ptr可以将A版本写为

template <typename T>
struct foo<std::unique_ptr<T>, 
           typename std::enable_if<std::is_class<
              std::unique_ptr<T>>::value>::type>
 { static int const value = 1; };
Run Code Online (Sandbox Code Playgroud)

或者你可以写foo如下

template <typename T,
          typename = typename std::enable_if<std::is_class<T>::value>::type> 
struct foo;

template <typename T>
struct foo<std::unique_ptr<T>>
 { static int const value = 1; };

template <typename T>
struct foo<T>
 { static int const value = 2; };
Run Code Online (Sandbox Code Playgroud)

因此,A变得比B您的代码可以编译的更加专业的版本。否则A,实际上您的版本是更专业的版本,B但编译器无法识别它。

观察与

template <typename T>
struct foo<std::unique_ptr<T>, 
           typename std::enable_if<std::is_class<
              std::unique_ptr<T>>::value>::type>
 { static int const value = 1; };
Run Code Online (Sandbox Code Playgroud)

代码编译,并且std::is_class<std::unique_prt<T>>::value永远真实的; 但是如果你写

template <typename T>
struct foo<std::unique_ptr<T>, 
           typename std::enable_if<true>::type>
 { static int const value = 1; };
Run Code Online (Sandbox Code Playgroud)

(实际上是等效的)代码无法编译

-编辑-

如果需要foo<std::unique_ptr<int>匹配的大小写B,则可以(例如)创建一个traits类型,如下所示

struct foo<T>
 { static int const value = 2; };

template <typename T>
struct proValue
   : std::integral_constant<int, 2>
 { };

template <typename T>
struct proValue<std::unique_ptr<T>>
   : std::integral_constant<int, std::is_class<T>::value ? 1 : 2>
 { };
Run Code Online (Sandbox Code Playgroud)

并定义foo如下

template <typename T, int = proValue<T>::value>
struct foo;

template <typename T>
struct foo<std::unique_ptr<T>, 1>
 { static int const value = 1; };

template <typename T>
struct foo<T, 2>
 { static int const value = 2; };
Run Code Online (Sandbox Code Playgroud)

以下是完整的可编译示例

#include <memory>
#include <vector>
#include <iostream>
#include <type_traits>

class Test
 { };

template <typename T,
          typename = typename std::enable_if<std::is_class<T>::value>::type> 
struct foo;

template <typename T>
struct foo<std::unique_ptr<T>>
 { static int const value = 1; };

template <typename T>
struct foo<T>
 { static int const value = 2; };

template <typename T>
struct proValue
   : std::integral_constant<int, 2>
 { };

template <typename T>
struct proValue<std::unique_ptr<T>>
   : std::integral_constant<int, std::is_class<T>::value ? 1 : 2>
 { };

template <typename T, int = proValue<T>::value>
struct bar;

template <typename T>
struct bar<std::unique_ptr<T>, 1>
 { static int const value = 1; };

template <typename T>
struct bar<T, 2>
 { static int const value = 2; };

int main ()
 {
   std::cout << foo<std::vector<int>>::value << '\n';      // print 2
   std::cout << foo<std::unique_ptr<int>>::value << '\n';  // print 1
   std::cout << foo<std::unique_ptr<Test>>::value << '\n'; // print 1

   std::cout << bar<std::vector<int>>::value << '\n';      // print 2
   std::cout << bar<std::unique_ptr<int>>::value << '\n';  // print 2
   std::cout << bar<std::unique_ptr<Test>>::value << '\n'; // print 1
 }
Run Code Online (Sandbox Code Playgroud)