10

我在想一个像这样的类:

template < typename ...Whatever >
class MyClass
{
public:
    static constexpr bool has_default_ctr = Something;

    // I want this only if "has_default_ctr" is "true".
    MyClass();

    //...
};

我认为我不能std::enable_if为此使用构造函数模板(因为没有参数)。我错了吗?如果没有,还有其他方法可以做到这一点吗?

4

8 回答 8

16

C++11 允许(可靠地)enable_if在模板参数中使用 -style SFINAE:

template<
    // This is needed to make the condition dependent
    bool B = has_default_ctr
    , typename std::enable_if<B, int>::type = 0
>
MyClass();

// When outside of class scope:
// have to repeat the condition for out-of-line definition
template<bool B, typename std::enable_if<B, int>::type = 0>
MyClass::MyClass()
/* define here */

在 C++03 中,您可以使用带有默认参数的一元构造函数——默认参数意味着构造函数仍然算作默认构造函数。

于 2012-04-25T05:16:24.323 回答
3

由于评论中提到了具有默认参数的解决方案,但我需要相当长的时间来弄清楚如何做到这一点(将我的 Enabler 类设为私有,这不起作用),这里是建议的解决方案,以防有人正在寻找它:

class MyClass {
public:
   // if constructor is supposed to be public,
   // this helper class must be public as well!
   struct Enabler {}; 

   template <class U = Enabler>
   MyClass (std::enable_if_t<has_default_ctr, U> = Enabler {})
   {
      // whatever
   }
};
于 2015-08-01T10:08:17.107 回答
1

要根据某些条件获得类的不同定义,请将依赖关系计算放在模板参数中。

// primary template, no default constructor unless Something is true
template< typename T, bool has_default_ctr = Something > class MyClass {
    // as you had it, with no default constructor
};

// you want MyClass<T,true> to be just like MyClass<T,false>
// but with a default constructor:
template< typename T > class MyClass<T,true> : public MyClass<T,false> {

    MyClass() : MyClass<T,false>(/* chosen constructor args */) { etc; }

    using MyClass<T,false>::MyClass<T,false>;
};

如果您没有 C++11,则不能使用using构造函数继承,您必须重新声明其所有构造函数并将它们的参数转发给基类。

这是手指对键盘的操作,我没有方便的编译器 atm,因此可能会出现轻微的语法错误。

于 2012-04-25T05:44:37.740 回答
0

你可以做一些简单的事情

template < typename ...Whatever >
class MyClass
{
public:
    static constexpr bool has_default_ctr = Something;

    // I want this only if "has_default_ctr" is "true".
    MyClass()
    {
        static_assert(has_default_ctr, "Not Default Constructible");
    }

    //...
};
于 2012-04-25T20:00:18.163 回答
0

enable_if很容易(如果类也模板化,它也可以工作):

#include <type_traits>

class MyClass
{
public:
    static constexpr bool has_default_ctr = Something;

    // I want this only if "has_default_ctr" is "true".
    template <typename = std::enable_if<has_default_ctr>::type>
    MyClass();

    //...
};
于 2019-12-17T09:55:55.207 回答
0

这是我最近使用的一个。如果它的数据成员支持默认构造函数,我需要一个带有默认构造函数的类模板,否则默认构造函数不应该编译。

类模板定义了模板类型参数,类定义了这种类型的数据成员(使用继承的变体也可能很有吸引力,因为它可以使用空基类优化)。数据成员的默认构造函数由类的默认构造函数自动调用。如果数据成员的类型没有默认构造函数,则编译失败。否则它会成功。这是代码:

#include <string>
template <typename Data>
class Demo
{
    Data d_data;

    public:
        Demo() = default;        // OK when used and Data has a default
                                 // constructor. 

        Demo(Data const &data)   // Exampe of an additional constructor
        :
            d_data(data)
        {}

        // ...
};

struct WithoutDefault
{
    WithoutDefault(int)
    {}
};

int main()
{
    Demo<std::string> withString;
    // Demo<NoDefault> nope;              // won't compile

    WithoutDefault nod(10);
    Demo<WithoutDefault> nodefault(nod);  // OK
}
于 2015-09-11T19:23:50.087 回答
0

可能的答案并不完全适合这个问题。但是,如果您只想在模板参数类型字段具有默认构造函数时为模板类启用默认构造函数。然后您可以在模板类中创建显式默认构造函数。参见示例:

struct HasDefault
{
    HasDefault() = default;
    HasDefault(int) {}
};

struct NoDefault
{
    NoDefault() = delete;
    NoDefault(int) {}
};

template <typename ValueT>
struct Wrapper
{
    Wrapper() = default;
    Wrapper(ValueT &&value) : value(std::forward<ValueT>(value)) {}

    ValueT value;
};

int main()
{
    Wrapper<HasDefault> hasDefault;
    Wrapper<HasDefault> hasDefault2(1);
    //Wrapper<NoDefault> noDefault; error: use of deleted function 'Wrapper<ValueT>::Wrapper()
    Wrapper<NoDefault> noDefault2(1);
}
于 2020-04-28T15:28:48.927 回答
-1

您可以使用具有不同参数的不同构造函数

MyClass(){

}
MyClass(int num){

}
MyClass(String s){
}

并且您可以简单地编写返回类并在其中写入条件的静态函数:

static chooseContructor(/*parameters*/){
 if(/*something*/){
     return new MyCLass();
 }
 else if(/*something else*/){
     return new MyClass(int num);
 }
 else if{
    return new MyClass(String s);
 }
}

等等......这样的东西会给你一个半自动的构造函数选择器

于 2012-04-25T05:02:50.770 回答