基于模板类型参数的条件成员签名和实现

时间:2017-09-26 12:07:19

标签: c++

我正在尝试编写一个包含多个类型参数T1T2的模板类。该类有一个std::promise<T2>类型的私有成员。

template <class T, class T2>
class Test
{
public:
    void setValue(T2 value)
    {
        promise.set_value(value);
    }

    void setValue()
    {
        promise.set_value();
    }

private:
    std::promise<T2> promise;
};

T2是空的时候,这个类编译得很好(只要你没有参数就调用setValue。当T2无效时,我得到编译错误:

error C2182: 'value' : illegal use of type 'void'

T2无效时,我想使用第一个setValue方法,该方法具有T2类型的单个参数。当T2无效时,我想使用第二个setValue方法,该方法不带参数。我看了很多例子,但我对模板编程比较陌生,而且我似乎无法使它工作。

是否有可能以某种方式使用std :: enable_if完成此操作?或者使用模板专业化?

2 个答案:

答案 0 :(得分:2)

帮助器模板类专业化:

#include <future>

template<typename T>
class TestHelper
{
public:
    void setValue(T const& v)
    { promise.set_value(v); }

private:
    std::promise<T> promise;
};

template<>
class TestHelper<void>
{
public:
    void setValue()
    { promise.set_value(); }

private:
    std::promise<void> promise;
};

template <class T, class T2>
class Test : public TestHelper<T2>
{
};

int main()
{
    Test<void, int> t;
    // t.setValue(); // compilation error: no matching function for call to 'std::promise<int>::set_value()'
    t.setValue(0);

    Test<void, void> t1;
    t1.setValue();
    // t1.setValue(0); // compilation error: no matching function for call to 'std::promise<void>::set_value(int)'
}

答案 1 :(得分:0)

您可以通过对基类的条件依赖来解决此问题:

#include <future>
#include <type_traits>
#include <iostream>

template<class T2>
struct Base {
protected:
    std::promise<T2> promise;
};

template<class T2>
struct BaseWithVariable : public Base<T2> {
    void setValue(T2 value)
    {
        this->promise.set_value(value);
    }
};

template<typename T2>
struct BaseWithoutVariable : public Base<T2> {
    void setValue()
    {
        this->promise.set_value();
    }
};

template<typename T, typename T2>
class Test
: public std::conditional<std::is_same_v<T2, void>, BaseWithoutVariable<T2>, BaseWithVariable<T2>>::type
{
};

int main()
{
    Test<int, int> a;
    a.setValue(5);
    Test<int, void> b;
    b.setValue();
}

现在你意识到你可以在中级的水平上实现同样的专业化:

template<class T2>
struct BaseSetter : public Base<T2> {
    void setValue(T2 value)
    {
        this->promise.set_value(value);
    }
};

template<>
struct BaseSetter<void> : public Base<void> {
    void setValue()
    {
        this->promise.set_value();
    }
};

template<typename T, typename T2>
class Test : public BaseSetter<T2>
{
};

在这种特殊情况下,如果省略Base的使用并且BaseSetter的两个变体都使用自己的成员变量std::promise<T2>,或{{}},也不会受到伤害。 1}},分别。

然而,所有这些都在GCC 7.2.0运行时崩溃。我不知道为什么。