为什么显式给出的模板参数不能是 "deduced"

why template parameter which is explicitely given can not be "deduced"

来自那个问题:

我尝试实现:

enum Specifier
{
    One,
    Two,
    Three
};

template <Specifier, typename UNUSED=void>
struct Foo 
{
        void Bar(){ std::cout << "Bar default" << std::endl;}
};

template <Specifier s , typename std::enable_if<s == Specifier::Two || s == Specifier::One, int>::type>
struct Foo<s>
{
    void Bar(){ std::cout << "Bar Two" << std::endl; }
};


int main()
{
   Foo< One >().Bar();
   Foo< Two >().Bar();
}

失败:

> main.cpp:130:8: error: template parameters not deducible in partial specialization:
  130 | struct Foo<s>
      |        ^~~~~~
   main.cpp:130:8: note:         '<anonymous>'

如何修复那个超级简单的例子?我喜欢 SFINAE :-)

enable_if 放入 Foo 的模板参数列表中:

template <Specifier s>
struct Foo<s, typename std::enable_if<s == Specifier::Two || s == Specifier::One, void>::type>
//                                           same as the default type used before ^^^^

demo.

模板特化中的模板参数是不可推导的,这是一个简单的事实。

不是你需要它。

只需更改模板专业化:

template <Specifier s>
struct Foo<s, std::enable_if_t<s == Specifier::Two || s == Specifier::One, int>>

虽然 std::enable_if_t 的结果当然是 int 而不是 void 使它有些无用。

此外,正如其他人评论的那样,使用概念或至少 requires 而不是主模板的额外模板参数要方便得多。

正如错误告诉我们的那样,模板参数在偏特化中是不可推导的。在您的示例中,您已尝试将 SFINAE 构造放置在专业化的模板 parameter 列表中,但您需要将其移动到模板 argument专业化声明的列表(class 被专业化)。

template <Specifier S>
struct Foo<S, std::enable_if_t<(S == Specifier::Two) || (S == Specifier::One)>>

应用于您的示例(稍作清理):

#include <iostream>
#include <type_traits>

enum class Specifier {
    One,
    Two,
    Three
};

template <Specifier, typename = void>
struct Foo {
    static void bar() { std::cout << "bar default\n"; }
};

template <Specifier S>
struct Foo<S, std::enable_if_t<(S == Specifier::Two) || (S == Specifier::One)>> {
    static void bar() { std::cout << "bar One or Two\n"; }
};

int main() {
    Foo<Specifier::One>::bar();    // bar One or Two
    Foo<Specifier::Two>::bar();    // bar One or Two
    Foo<Specifier::Three>::bar();  // bar default
}

请注意,您无需在 class 模板的主模板中命名未使用的类型模板参数 Foo