我应该如何有条件地启用构造函数?

How should I conditionally enable a constructor?

我正在努力实现这样的目标:

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 ,但我不想复制通用代码。

那么,这是最好的(或至少是明智的)选择吗?

Is there any disadvantage of this solution?

目前,替换发生在直接上下文之外,因此一旦您尝试使用 [=12] 无法构造的类型实例化 foo,您的方法就会 cause a hard compilation error =].

要引入直接上下文,您需要一个虚拟参数:

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

DEMO