如何防止用户指定功能模板参数,迫使其推导?

Hol*_*Cat 8 c++

假设我有一个模板函数:

template <typename A, typename B>
A fancy_cast(B)
{
    return {};
}
Run Code Online (Sandbox Code Playgroud)

预期的用法类似于fancy_cast<int>(1.f)

但是,没有什么可以阻止用户手动指定第二个模板参数:fancy_cast<int, int>(1.f),这会引起问题。

如何防止typename B被指定并强制推断?

我想出了这个:

// Using this wrapper prevents the code from being
// ill-formed NDR due to [temp.res]/8.3
template <auto V> inline constexpr auto constant_value = V;

template <
    typename A,
    typename ...Dummy,
    typename B,
    typename = std::enable_if_t<constant_value<sizeof...(Dummy)> == 0>
>
A fancy_cast(B)
{
    return {};
}
Run Code Online (Sandbox Code Playgroud)

它似乎可以工作,但是非常麻烦。有没有更好的办法?

Hol*_*Cat 2

我找到了一个不错的解决方案。

我们可以使用用户无法构造的类型的非类型参数包。1例如对隐藏类的引用:

namespace impl
{
    class require_deduction_helper
    {
      protected:
        constexpr require_deduction_helper() {}
    };
}

using require_deduction = impl::require_deduction_helper &;

template <typename A, require_deduction..., typename B>
A fancy_cast(B)
{
    return {};
}
Run Code Online (Sandbox Code Playgroud)

1我们必须在构造 a 时留下一个漏洞deduction_barrier,否则代码将是格式错误的 NDR。这就是构造函数受到保护的原因。