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

时间:2017-07-10 09:38:19

标签: c++ templates

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

session_start();
if (!isset($_SESSION['nID']) || empty($_SESSION['nId'])) {
   header("Location: login.php");
   die();
}

我有一个初始化函数。

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;
}

显然,当template<class T> void initialize(T &val) { if (is_pointer(val)) val = NULL; else val = T(); } T时,无法编译此代码。有什么方法可以在string是指针类型时编译val = NULL并在T不是指针类型时编译val = T()

3 个答案:

答案 0 :(得分:20)

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

val = T{};

此外,标准库提供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();
    }
    
  • 在C ++ 14中,您can implement your own 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); }
    

答案 1 :(得分: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();
}

答案 2 :(得分:6)

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

template<class T>
void initialize(T& val)
{
    val = T();
}
template<class T>
void initialize(T*& val)
{
    val = NULL;
}

但是,第一个重载(在特定情况下)也包含指针,所以第二个实际上已经过时了。

无论是否过时,我希望nullptr关键字超过NULL宏(尽管再次失去了C ++ 11之前的兼容性)。