模板化类-如果启用

时间:2018-06-19 18:07:46

标签: c++ templates compilation

我试图做一个仅在某些情况下运行函数的模板化类。这是我的代码:

#include "stdafx.h"
#include <string>
#include <iostream>


template <class T, class U>
struct Typelist
{
    typedef T Head;
    typedef U Tail;
};

class NullType
{
};

typedef Typelist<int, Typelist<float, Typelist<char*, NullType> > > UsableTypes1;
typedef Typelist<short, Typelist<std::string, NullType> > UsableTypes2;

template <class T>
class MyClass
{
public:
    MyClass();

private:
    Typelist _types;
};


template<class T>
MyClass<T>::MyClass()
{
    _types = T;
}

template<class T>
void MyClass<T>::print(T type)
{

}

MyClass<UsableTypes1> any;

我不仅需要传递给print()函数的变量是一种可用类型的类型,还需要使代码编译。我知道,如果使用不正确的类型调用print,可能必须使用std :: enable_if来允许代码编译或不使用,而使用std :: is_same来检查类型,但是我不知道如何组合该函数带有模板化的类。

这是一个测试类,可以帮助解释我要实现的目标:

MyClass<UsableTypes1> one;

void TestMyClass()
{
    int int_val = 0;
    float flt_val = 0.1f;
    const char* char_val = "Hi";
    short short_val = 10;
    std::string str_val = "Hello";

    one.print(int_val); // OK
    one.print(flt_val); // OK
    one.print(char_val); // OK
                              //    one.print( short_val); // compile error
                              //    one.print( str_val ); // compile error
}

特别是我不知道如何向print()添加一个非T型参数。

希望您能帮助我! 预先谢谢你。

1 个答案:

答案 0 :(得分:1)

我不知道您是否有充分的理由使用递归Typelist来包含类型列表。更直接的方法是使Typelist为可变参数模板。

然后,我们可以添加一个constexpr函数,如果给定类型是Typelist的一部分,则该函数返回true。

std::disjunction需要c++17,但是可以使用递归模板为c++11编写等效的内容。但是那会更加冗长。

#include <iostream>
#include <type_traits>

struct NullType {};

template <typename T, typename U>
struct Typelist {
    using Head = T;
    using Tail = U;
    template <typename Type>
    static constexpr bool IsUsable() {
        return std::is_same<Type, T>::value;
    }
};

template <typename T, typename... U>
struct Typelist<T, Typelist<U...>> {
    using Head = T;
    using Tail = Typelist<U...>;
    template <typename Type>
    static constexpr bool IsUsable() {
        return std::is_same<Type, T>::value || Typelist<U...>::template IsUsable<Type>();
    }
};

using UsableTypes1 = Typelist<int, Typelist<float, Typelist<const char*, NullType>>>;

template <class T>
class MyClass
{
public:
    template <typename U>
    void print(U u) {
        static_assert(T::template IsUsable<U>(), "That is not a usable type");
        std::cout << u << std::endl;
    }
};

MyClass<UsableTypes1> one;

int main()
{
    int int_val = 0;
    float flt_val = 0.1f;
    const char* char_val = "Hi";
    short short_val = 10;
    std::string str_val = "Hello";

    one.print(int_val); // OK
    one.print(flt_val); // OK
    one.print(char_val); // OK
                              //    one.print( short_val); // compile error
                              //    one.print( str_val ); // compile error
}