【问题标题】:How to write a traits conversion to add 'const' to type*如何编写特征转换以将“const”添加到类型*
【发布时间】:2017-04-03 15:59:36
【问题描述】:

是否可以有一个特征来将char* 转换为const char*,以便进一步使用它来调用具有const char* 参数的函数,使用char* 变量?

我有这个(上下文很大,我已经简化了,对丑陋的代码感到抱歉):

#include <iostream>
using namespace std;
#include <stdio.h>
#include <string.h>
#include <typeinfo>

template<typename T, typename U, std::enable_if_t<std::is_same<T, U>::value, int> = 0>
T convert_type(U _in)
{
    return _in;
}

template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<U>>::value, int> = 0>
T& convert_type(U& _in)
{
    return _in;
}

template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_lvalue_reference_t<std::add_const_t<U>>>::value, int> = 0>
T& convert_type(U& _in)
{
    return _in;
}

template<typename T, typename U, std::enable_if_t<std::is_same<T, std::add_pointer_t<U>>::value, int> = 0>
T convert_type(U& _in)
{
    return std::addressof(_in);
}

int main() {

    char* c = new char[sizeof "test"];
    strcpy(c, "test");

    const char * cc = convert_type<const char *, char *>(c); // here not compilable yet due to lack of the right convert_type specialization

    cout << c;

    delete[] c;
    return 0;
}

为了澄清,我将 SpiderMonkey 嵌入到脚本 Illustrator API 中。这让我编写了相当复杂的代码,但我已经检查过并且我知道上面的转换特征用于各种函数调用。我在这里添加它们只是为了查看方法并阐明添加另一个识别类型并返回所需类型的需要。您所有的 cmets 通常都是正确的,但在我的上下文中并非如此。我可能有一个复杂的代码,但我已经尽可能地简化了。

示例代码here

就我而言,问题尚未得到解答,我也找不到解决方案。我这样提出问题:如何编写一个特征方法来匹配char*const char*,即char const*,实际上,当我使用typeid 签入msvc 时,声明为const char* 的类型或变量?

【问题讨论】:

  • 直接转换成 const char* 怎么样?
  • static_cast 有什么问题?
  • char*const char* 隐式发生。
  • 我不认为 char * c = "test"; 是有效的 C++
  • @mike 至于你的编辑,你可能简化你的真实代码太多了。尝试提供一个minimal reproducible example,清楚地表明您的实际问题。

标签: c++ c++11


【解决方案1】:

是否可以有一个特征来将char* 转换为const char*,以便进一步使用它来调用具有const char* 参数的函数,使用char* 变量?

正如 cmets 中所指出的,根本不需要进行特征转换,因为 char* 指针可以随时与 const char* 指针同等使用,因为转换是隐式的(对于任何其他输入比char)。


注意main() 函数中的行

char * c = "test";

不是有效的 C++ 语法。 "test" 实际上是 const char [5] 类型,您不能合法地将其分配给 const char* 指针以外的其他类型。
至少任何向该指针写入值的尝试都是未定义的行为

大多数符合 c++11 的编译器都会对该语句发出警告。


至于您现在编辑的示例

char* c = new char[sizeof "test"];
strcpy(c, "test");

//const char * cc = convert_type<const char *, char *>(c);

不需要使用convert_type() traits 函数,你可以简单地写(在 cmets 中也提到过):

const char * cc = c;

【讨论】:

    【解决方案2】:

    (为了“保卫”OP:是的,我也想过简单地添加const,因为const const Tconst T 相同,但是另一方面,我可以想到情况,你有传递一个除此之外什么都不做的类型特征。) 怎么样:

    // ordinary way w/o type aliases
    template<typename T>
    struct const_qualify
    {
        typedef const T type;
    };
    
    // do this if you have type aliases
    template<typename T>
    using const_qualify_t = const T;
    

    注意,如果你只是想比较类型,我们现在有 remove_const / remove_cv:http://en.cppreference.com/w/cpp/types/remove_cv

    编辑:实际上,我们也有std::add_const&lt;&gt;

    【讨论】:

    • 感谢您对我的信任,在已经存在简单明了的方法的情况下,我不是简单地编写一段无用的代码来进行复杂分配的傻瓜。你感觉对了,看来我需要一个新的convert_type&lt;typename T, typename U, condition&gt; 重载或通过其condition 进行专门化来检测T 是const 并返回正确的东西。我仍在寻找它或重写所有convert 函数以实现目标的方法。
    • 是的,我想比较类型,但是我不能用remove_constremove_ct写一些类似于上面convert_type的方法。
    • 这和std::add_conststd::add_const_t有区别吗?
    • @user2023370: 都一样,上面只是一个实现。
    【解决方案3】:

    只使用赋值:

    const char* cc = c;
    

    (注意char* c = "test" 格式错误)

    更明确地说,这绝不是一件坏事,您可以使用标准 C++ 强制转换之一:

    auto cc = static_cast<const char*>(c);
    

    您的前三个convert_type() 重载基本上是无用的 - 只需使用= 即可轻松替换所有这些。而= 实际上也比您的convert_type() 处理更多案件。

    第四个重载应该替换为&amp;(或直接使用std::addressof),真的没有必要隐藏你正在获取地址。当然T* x = &amp;yT* x = convert_type&lt;T*&gt;(y) 的含义更容易理解。

    【讨论】:

      【解决方案4】:

      最终,我成功了,使用this post

      template<typename T> struct remove_all_const : std::remove_const<T> {};
      
      template<typename T> struct remove_all_const<T*> {
          typedef typename remove_all_const<T>::type *type;
      };
      
      template<typename T> struct remove_all_const<T * const> {
          typedef typename remove_all_const<T>::type *type;
      };
      
      
      template<typename T, typename U, std::enable_if_t<std::is_same<typename remove_all_const<T>::type, typename remove_all_const<U>::type>::value, int> = 0>
      T convert_type(U& _in)
      {
          return _in;
      }
      

      给那个帖子求解器一个大的Thank!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-08-16
        • 1970-01-01
        • 2016-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多