如何更好地禁用特定函数参数的模板参数推导?

14
这是我想要做的事情:
template <typename T> void f(DisableDeduction<T> obj) {std::cout << obj;}
// Here DisableDeduction<T> aliases T, but in a such way
// that would prevent compiler from deducing T based
// on provided argument.

/* ... */

f<int>(1); // Works.
f(1); // Error, can't deduce template parameter based on argument.

这是我目前的实现方式:
template <typename T> struct DisableDeduction_Internal {using type = T;};
template <typename T> using DisableDeduction = typename DisableDeduction_Internal<T>::type;

它完美地运作(如描述所示),但它引入了一个额外的辅助类型。
但是,我能否在不使用额外类型的情况下达到相同的结果?

3
std::enable_if_t<true, T> ? - Jarod42
@Jarod42,您能否将其转换为带有工作示例的答案? - Parker Coates
自从C++20以来,只需使用std::type_identity_t - underscore_d
2个回答

14
你可以通过将T放在不可推导的上下文中(在::左侧),并使用<type_traits>中的std::common_type来实现。
示例:
template <typename T> void f(typename std::common_type<T>::type obj) {std::cout << obj;}

谢谢。我会把它放进一个模板using中(和以前一样),以便更方便地使用。 - HolyBlackCat
在C++14中,typename std::common_type<T>::type可以简写为std::common_type_t<T>(我认为这样更短更易读)。 - Léo Lam
通过typedef更易读,template<typename T> using no_infer = typename std::common_type<T>::type; - Eric

3
自C++20起,您可以使用std::type_identity_t<T>
在C++20之前,我建议使用std::enable_if_t<true, T>std::common_type_t<T>看似无害,但会应用std::decay到类型上,移除constvolatile和/或引用性。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接