如何正确定义模板化类的成员结构的部分特化?

时间:2018-06-06 14:41:23

标签: visual-studio templates c++17 partial-specialization

我在尝试为模板化成员结构添加std :: iterator_traits时遇到错误 - 即我有一个迭代器类,它是模板化外部类的成员:

namespace Toolbox {
    template <typename CharType>
    class substring_container_adapter
    {
    public:
        struct iterator // : public std::iterator<std::forward_iterator_tag, const CharType *>   C++ 17 is very upset at this approach!
        {
            // iterator constructor
            iterator(const CharType * pszPosition, const CharType * pszDelimeters)

后来,我尝试为std添加一个部分特化迭代器特征,因为显然继承了std :: iterator(尽管那个 - 或者boost :: iterator_adaptor&lt;&gt;非常有意义,并且实际上在这个和其他方面有效)上下文)...

// define iterator traits for our custom iterators
namespace std 
{
    template <typename CharType>
    struct iterator_traits<class Toolbox::substring_container_adapter<CharType>::iterator>
    {
        using iterator_category = forward_iterator_tag;
        using value_type = CharType;
    };
}

然而,VC ++ 2017版本15.7.3(为此项目启用了C ++ 17)抱怨:

  

错误C2764:'CharType':在部分特化'std :: iterator_traits :: iterator&gt;'中未使用或可推导的模板参数

为什么不呢?

我怀疑这是!@#$恼人的限制,因为尝试部分特化成员结构而不是substring_container_adapter&lt;&gt;之外的模板化结构?

1 个答案:

答案 0 :(得分:2)

这里要做的正确的事情是将类型别名放在std::iterator_traits中,而不是尝试部分专门化namespace Toolbox { template <typename CharType> class substring_container_adapter { public: struct iterator // : public std::iterator<std::forward_iterator_tag, const CharType *> C++ 17 is very upset at this approach! { using iterator_category = forward_iterator_tag; using value_type = const CharType *; using reference = const CharType * &; using pointer = const CharType * *; using difference_type = std::ptrdiff_t; // iterator constructor iterator(value_type pszPosition, value_type pszDelimeters) // ... } } }

std::iterator

弃用Iterators的一个主要原因是委员会不喜欢它给出的印象,即所有namespace not_std { template<class Category, class T, class Distance = ptrdiff_t, class Pointer = T*, class Reference = T&> struct iterator { using iterator_category = Category; using value_type = T; using difference_type = Distance; using pointer = Pointer; using reference = Reference; }; } 应该来自它,因为没有任何容器迭代器需要。您可以定义确切的替换

global $wpdb, $post;

    //give prefix
    $info = pathinfo( $filename );      //need to take default filename during uploading
    $type = $info['extension'];
    if ( $type == 'jpg' || $type == 'jpeg' || $type == 'png' ) {
        $prefix = 'img_';
    } elseif ( $type == 'pdf' || $type == 'txt' || $type == 'docx' || $type == 'doc' || $type == 'xlsx' || $type == 'xls'  ) {
        $prefix = 'doc_';
    } elseif ( $type == 'mp4' || $type == 'avi' ) {
        $prefix = 'mov_';
    } elseif ( $type == 'gif' ) {
        $prefix = 'gif_';
    } else {
        $prefix = 'file_';
    }

    if (!is_super_admin()) {

       do { 
        $ext = empty( $info['extension'] ) ? '' : '.' . $info['extension'];
        $rand = rand(123456789,987654321);
        $newname = $prefix . $rand . $ext;

        //cheker
            $namecheck = $prefix . $rand;
            $attachment_id = $post->ID;
            $check_sql = "SELECT post_name FROM $wpdb->posts WHERE post_name = %s AND ID != %d LIMIT 1";
            $attachment_slug_exist_check = $wpdb->get_var( $wpdb->prepare( $check_sql, $namecheck, $attachment_id ) );

        //cheker            
            $upload_dir = wp_get_upload_dir();
            $file_exist_check = file_exists( $upload_dir['path'] . DIRECTORY_SEPARATOR . $newname );

        //cheker    
            if ( $file_exist_check || $attachment_slug_exist_check ) {
            $check = true;
            } else {
            $check = false;
            }

            $newtitle = $prefix . $rand;

       } while ( $check );
    } else {
    $newname = $oldname;    //need to take default name
    $newtitle = $oldtitle;  //need to take default name
    }


    $current_user = wp_get_current_user();
    if ( !is_user_logged_in() ) {               
    $username = '/trash';                                   
    } elseif ( is_super_admin() || current_user_can('administrator') ) {            
    $username = '';                                     
    } else {
    $username = '/users/' . $current_user->user_login;                  
    }

    //full changed url
    $newslug = $username . '/attachment/' . $newtitle;

    return $newslug;
    return $newname;
    return $newtitle;