我可以在C++中部分编译模板函数

How*_*ard 15 c++ templates

我有一个函数来确定模板类型是否为指针.

template<class T>
struct is_pointer_struct { static const bool value = false; };

template<class T>
struct is_pointer_struct<T*> { static const bool value = true; };

template<class T>
bool is_pointer(T &var) {
    return is_pointer_struct<T>::value;
}
Run Code Online (Sandbox Code Playgroud)

我有一个初始化函数.

template<class T>
void initialize(T &val) {
    if (is_pointer(val))
        val = NULL;
    else
        val = T();
}
Run Code Online (Sandbox Code Playgroud)

显然,当Tstring,此代码不能被编译.有没有一种方法可以val = NULLT指针类型时编译并val = T()T不是指针类型时编译?

Vit*_*meo 20

在您的特定情况下,您可以使用统一初始化,因为VTT说:

val = T{};
Run Code Online (Sandbox Code Playgroud)

此外,标准库提供std::is_pointer.


作为更一般的问题的答案"如何在编译时分支?" :

  • 在C++ 17中,您所要做的就是将您更改if(...)if constexpr(...):

    template<class T>
    void initialize(T &val) {
        if constexpr(is_pointer(val))
            val = nullptr;
        else
            val = T();
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 在C++ 14中,您可以实现自己的static_if.

  • 在C++ 03/11中,您可以使用标签分派:

    template <typename T>
    void initialize_impl(std::true_type /* pointer */, T& val)
    {
        val = NULL;
    }
    
    template <typename T>
    void initialize_impl(std::false_type /* non-pointer */, T& val)
    {
        val = T();
    }
    
    template<class T>
    void initialize(T &val) { initialize_impl(std::is_pointer<T>{}, val); }
    
    Run Code Online (Sandbox Code Playgroud)


Edg*_*jān 6

在你的情况下做正确的事情的正确方法是使用统一初始化,如上所述.

作为一个选项,您可以根据您的类型特征使用SFINAE,以便实例化必要的模板(这是一种C++ 11方法):

template<class T>
auto initialize(T &val) ->
    typename std::enable_if<is_pointer_struct<T>::value>::type {
        val = nullptr;
}

template<class T>
auto initialize(T &val) ->
    typename std::enable_if<!is_pointer_struct<T>::value>::type {
        val = T();
}
Run Code Online (Sandbox Code Playgroud)


Aco*_*gua 6

经典解决方案,甚至不需要C++ 11功能:简单的重载:

template<class T>
void initialize(T& val)
{
    val = T();
}
template<class T>
void initialize(T*& val)
{
    val = NULL;
}
Run Code Online (Sandbox Code Playgroud)

但是,第一个重载(在特定情况下)也包含指针,因此第二个重载实际上是过时的.

无视过时,我更喜欢nullptr关键字而不是NULL宏(虽然再次失去了预C++ 11的兼容性).