template<bool, class T, class U>
struct IF_ELSE { using type = T; };
template<class T, class U>
struct IF_ELSE<false, T, Y> { using type = U; }
template<class T>
class Object {
Object baz(IF_ELSE<boolean_condition<T>::value, foo_class, bar_class>::type param) {
return Object(param);
}
};
您好我正在尝试创建一个方法,该方法返回一个基于某些模板条件初始化的对象。上面的代码工作正常,但我想使用默认构造函数(没有参数)
template<class T>
class Object {
Object baz(IF_ELSE<boolean_condition<T>::value, foo_class, void>::type param) {
return Object(param);
}
};
然而,不可能使用void作为一种类型(尽管void foo(void);
是有效的decleration)
反正有没有这样做?
笔记。我不想使用模板专业化。虽然这是针对这个特定问题的解决方案,但在我当前的项目中使用专业化会很不方便。我个人更喜欢使用IF_ELSE而不是专业化,因为我发现它更容易理解。
我能想到的唯一解决方法就是......
template<class T>
class Object {
Object baz(IF_ELSE<boolean_condition<T>::value, foo_class, int>::type param = 0) {
if (param == 0)
return Object();
else
return Object(param);
}
};
如果有人有一个更复杂的解决方案,那将是伟大的。非常感谢。
---------------------------------- EDITED --------------- ---------------
这种解决方法更好一些(受Oisyn的启发)它或多或少地结合了参数专业化和默认参数两者的优点。可能会有点快,因为它躲过if语句。
template<class T>
class Object
{
public:
struct MAKE_ILLEGAL {};
template<class param>
Object(param p) {/*do stuff */}
Object() {/* default */ }
template<bool b>
Object<T> baz(std::conditional_t<b, int, MAKE_ILLEGAL> param)
{ return Object<T>(param); }
template<bool b>
Object<T> baz(std::conditional_t<b, MAKE_ILLEGAL, int> value = 0)
{ return Object<T>(); }
};
int main() {
Object<double> obj;
obj.baz<false>();
}
编辑显然,你不允许在类型相关的上下文中使用解析为void
的函数作为函数参数。我使用不同的解决方案相应地编辑了我的答案。原始答案可以在下面阅读。
// A helper that always yields true so we can make the condition type-dependent
// on arbitrary template parameters
template<class T>
constexpr bool true_v = true;
template<class T>
class Object
{
public:
template<class U = void, std::enable_if_t<Condition<T>::value && true_v<U>, int> = 0>
Object baz(foo_class param)
{ return Object(param); }
template<class U = void, std::enable_if_t<!Condition<T>::value && true_v<U>, int> = 0>
Object baz()
{ return Object(); }
};
只要我们不处理特殊方法,如复制/移动ctors和复制/移动赋值操作符(可能没有模板化),我们总是可以应用常规的SFINAE技巧。我们只需要使用默认模板参数来模板化baz
,并确保用于std::enable_if
的条件依赖于该方法的模板参数(而不仅仅是T
中的Object<T>
)
原始答案
template<class T>
class Object
{
private:
struct dummy { };
public:
Object baz(std::conditional_t<Conditional<T>::value, foo_class, dummy> param)
{ return Object(param); }
Object baz(std::conditional_t<Conditional<T>::value, dummy, void>)
{ return Object(); }
};
我们的想法是创建两个重载,一个用于单个参数,一个用于无。通过有选择地用不可访问的虚拟类型替换参数,您可以确保在不合适时永远无法调用该过载。