2016-02-27 42 views
0

我想实现这样的事情:我应该如何有条件地启用构造函数?

template<typename Bar> 
class foo 
{ 
public: 
    template<class = std::enable_if_t<std::is_constructible<Bar, int>::value>> 
    foo(int x) 
     : m_bar(x) 
    { } 

private: 
    Bar m_bar; 
}; 

这就产生行为

foo<int> a; // no error 
foo<int> b(0); // no error 
foo<std::string> c; // no error 
foo<std::string> d(0); // error: none of the 3 overloads could convert all the argument types 

预期。这个解决方案有什么缺点吗?我不喜欢的是在任何情况下都存在foo::foo(int)。我知道我可以在foo本身的模板参数列表中使用enable_if,并且在这两种情况下可以使用foo,但我不想复制公共代码。

所以,这是最好的(或至少是明智的)选项?

+0

您是不是要找'Bar',而不是'T',或者,你的意思是'T类? = Bar,class = std :: enable_if ...' –

+0

@PiotrSkotnicki是的,当然。抱歉。 – 0xbadf00d

+0

目前,没有即时的上下文,所以它将无法编译而不是“禁用”构造函数 –

回答

3

这个解决方案有什么缺点吗?

目前,置换发生的直接背景之外,所以你的方法将cause a hard compilation error只要你尝试实例foo与类型不是constructible与int

要引入即时背景下,你需要一个虚拟参数:

template <typename T = Bar 
//     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~v 
     , typename = std::enable_if_t<std::is_constructible<T, int>::value>> 
foo(int x) 
    : m_bar(x) 
{ } 

DEMO

+0

虽然我不确定这是否是您主要关心的问题 –

+0

我已编辑该问题并在代码中添加了示例用法这个问题。 “只要尝试用不能用”int“构造的类型实例化'foo',你的方法就会导致编译错误。这似乎是错误的。编译错误不会发生,除非我尝试使用'int'参数构造函数。这就是理想的行为,不是吗? – 0xbadf00d

+0

@ 0xbadf00d不,我添加了演示 –

相关问题