C++ 根据模板参数选择构造函数

C++ 根据模板参数选择构造函数,c++,c++11,templates,C++,C++11,Templates,我想根据模板参数的值修改一个类函数。使用post,所有成员函数都可以根据模板参数进行不同的编写,这非常有效。问题是这个示例使用的是函数的返回类型,所以它不能与构造函数一起工作。基于post和post,我尝试了: // I'm using gcc 4.8.4 so have to define enable_if_t myself although // I guess it's not really needed template< bool B, class T = void >

我想根据模板参数的值修改一个类函数。使用post,所有成员函数都可以根据模板参数进行不同的编写,这非常有效。问题是这个示例使用的是函数的返回类型,所以它不能与构造函数一起工作。基于post和post,我尝试了:

// I'm using gcc 4.8.4 so have to define enable_if_t myself although 
// I guess it's not really needed

template< bool B, class T = void >
using enable_if_t = typename std::enable_if<B,T>::type;

template<class T, std::size_t CAPACITY, bool USE_THREADS = true>
class C_FIFO
{
public:
//...other ctor defs

    template<bool trigger = USE_THREADS, enable_if_t<not trigger>* = nullptr >
    C_FIFO(const C_FIFO& that):
        m_buf_capacity(CAPACITY + 1), m_in_ctr(0), m_out_ctr(0), m_wait(true)
    {
        m_buffer_data = that.m_buffer_data;
        m_in_ctr = that.m_in_ctr;
        m_out_ctr = that.m_out_ctr;
        m_wait    = that.m_wait.load();
    }
// more stuff
}
//我使用的是gcc 4.8.4,因此必须自己定义enable\u
//我想这不是真的需要
模板
使用enable_if_t=typename std::enable_if::type;
模板
C类先进先出
{
公众:
//…其他定义
模板
C_FIFO(const C_FIFO&that):
m_buf_容量(容量+1)、m_输入中心(0)、m_输出中心(0)、m_等待(真)
{
m_buffer_data=该.m_buffer_data;
m_in_ctr=该.m_in_ctr;
m_out_ctr=该.m_out_ctr;
m_wait=that.m_wait.load();
}
//更多的东西
}

模板
C类先进先出
{
公众:
//…其他定义
模板
//启用\u如果\u t
C_FIFO(const C_FIFO&that,如果t=false则启用):
m_buf_容量(容量+1)、m_输入中心(0)、m_输出中心(0)、m_等待(真)
{
m_buffer_data=该.m_buffer_data;
m_in_ctr=该.m_in_ctr;
m_out_ctr=该.m_out_ctr;
m_wait=that.m_wait.load();
}
//其他东西
}

但在这两种情况下,编译器都会尝试使用默认的复制构造函数,该构造函数会被删除,因为该类包含不可复制的类型(互斥和条件变量)。这两种情况似乎都应该有效,但显然我没有看到什么:)。任何指针(没有双关语)都将受到欢迎。

遗憾的是,构造函数不如函数灵活

using namespace std;
struct S
{
    template<typename T>
    S(typename enable_if<is_same<T, int>::value>::type* = nullptr)
    { cout << "T is int" << endl; }
    template<typename T>
    S(typename enable_if<!is_same<T, int>::value>::type* = nullptr)
    { cout << "T is not int" << endl; }
};

//this works, T is not int
S s;

//these all don't work
auto s = S<int>();
S s<int>();
S s<int>{};
使用名称空间std;
结构
{
模板
S(如果::type*=nullptr,则类型名为enable_)

{cout我使用委托构造函数实现了@PiotrSkotnicki的答案,但很快在赋值操作符上遇到了类似的问题(实际上问题更大,因为你不能用额外的参数重载它)。尽管我能够解决这两个问题,但做了一点小小的调整:

template<class T, std::size_t CAPACITY, bool USE_THREADS = true>
class C_FIFO
{
public:
    C_FIFO(): m_buf_capacity(CAPACITY + 1), m_in_ctr(0), m_out_ctr(0),
        m_wait(true) { }

    // copy constructor needs to be fancy because the mutex is not copyable or
    // movable.  Uses private helper functions to pick single or
    // multi-threaded version

    C_FIFO(const C_FIFO &that):m_buf_capacity(CAPACITY + 1)
    {
        copy_fifo(that, std::integral_constant<bool, USE_THREADS>{});
    }

    C_FIFO& operator=(const C_FIFO& that)
    {
        return copy_fifo(that, std::integral_constant<bool, USE_THREADS>{});
    }
// other public methods here

private:
    C_FIFO& copy_fifo(const C_FIFO& that, std::true_type)
    {
        std::unique_lock<std::mutex> this_lock(this->m_lock, std::defer_lock);
        std::unique_lock<std::mutex> that_lock(that.m_lock, std::defer_lock);
        std::lock(this_lock, that_lock);

        m_buffer_data = that.m_buffer_data;
        m_in_ctr = that.m_in_ctr;
        m_out_ctr = that.m_out_ctr;
        m_wait    = that.m_wait.load();
        return *this;
    }


    C_FIFO& copy_fifo(const C_FIFO& that, std::false_type)
    {
        m_buffer_data = that.m_buffer_data;
        m_in_ctr = that.m_in_ctr;
        m_out_ctr = that.m_out_ctr;
        m_wait    = that.m_wait.load();
        return *this;
    }

};
模板
C类先进先出
{
公众:
C_FIFO():m_buf_容量(容量+1),m_输入中心(0),m_输出中心(0),
m_wait(真){}
//复制构造函数需要花哨,因为互斥体不可复制或
//可移动。使用私人助手函数选择单个或多个
//多线程版本
C_FIFO(const C_FIFO&that):m_buf_容量(容量+1)
{
copy_fifo(即std::integral_常量{});
}
C_FIFO&运算符=(const C_FIFO&that)
{
返回copy_fifo(即std::integral_常量{});
}
//这里还有其他公共方法
私人:
C_FIFO和复制_FIFO(常量C_FIFO和THE,标准::真_类型)
{
std::unique\u lock this\u lock(this->m\u lock,std::defer\u lock);
std::唯一的_锁,即_锁(that.m_锁,std::延迟_锁);
锁(这个锁,那个锁);
m_buffer_data=该.m_buffer_data;
m_in_ctr=该.m_in_ctr;
m_out_ctr=该.m_out_ctr;
m_wait=that.m_wait.load();
归还*这个;
}
C_FIFO和copy_FIFO(常量C_FIFO和THY,标准::false_类型)
{
m_buffer_data=该.m_buffer_data;
m_in_ctr=该.m_in_ctr;
m_out_ctr=该.m_out_ctr;
m_wait=that.m_wait.load();
归还*这个;
}
};

like?我也看到了那篇文章——我会试试看。我想,因为我已经看到了那些其他的文章,它们更接近我已经在做的事情(使用enable\u if),为了保持一致性,我希望能坚持这样做。我还在试图了解整个SFINAE范式,所以我希望能理解它们为什么不起作用。这种方法会引入额外的复制操作吗?不,不会。当然不会——感谢上帝提供的参考。谢谢。那篇文章中的方法很有效。谢谢@PiotrSk奥特尼基
using namespace std;
struct S
{
    template<typename T>
    S(T*, typename enable_if<is_same<T, int>::value>::type* = nullptr);
};

template<typename T>
S make_S(typename enable_if<is_same<T, int>::value>::type* = nullptr);

S s((int*)nullptr);  //god awfully ugly
auto s = make_S<int>();  //hope for elision, must be copyable/moveable
template<class T, std::size_t CAPACITY, bool USE_THREADS = true>
class C_FIFO
{
public:
    C_FIFO(): m_buf_capacity(CAPACITY + 1), m_in_ctr(0), m_out_ctr(0),
        m_wait(true) { }

    // copy constructor needs to be fancy because the mutex is not copyable or
    // movable.  Uses private helper functions to pick single or
    // multi-threaded version

    C_FIFO(const C_FIFO &that):m_buf_capacity(CAPACITY + 1)
    {
        copy_fifo(that, std::integral_constant<bool, USE_THREADS>{});
    }

    C_FIFO& operator=(const C_FIFO& that)
    {
        return copy_fifo(that, std::integral_constant<bool, USE_THREADS>{});
    }
// other public methods here

private:
    C_FIFO& copy_fifo(const C_FIFO& that, std::true_type)
    {
        std::unique_lock<std::mutex> this_lock(this->m_lock, std::defer_lock);
        std::unique_lock<std::mutex> that_lock(that.m_lock, std::defer_lock);
        std::lock(this_lock, that_lock);

        m_buffer_data = that.m_buffer_data;
        m_in_ctr = that.m_in_ctr;
        m_out_ctr = that.m_out_ctr;
        m_wait    = that.m_wait.load();
        return *this;
    }


    C_FIFO& copy_fifo(const C_FIFO& that, std::false_type)
    {
        m_buffer_data = that.m_buffer_data;
        m_in_ctr = that.m_in_ctr;
        m_out_ctr = that.m_out_ctr;
        m_wait    = that.m_wait.load();
        return *this;
    }

};