无效的静态演员表
Posted
技术标签:
【中文标题】无效的静态演员表【英文标题】:Invalid Static Cast 【发布时间】:2014-11-06 12:34:10 【问题描述】:我从这里获取了代码:
http://en.wikipedia.org/wiki/Variadic_template
但是它将 uint8_t 和 int8_t 视为 ASCII,因此我想将任何内容转换为 int16_t。我试着这样做:
template<typename T, typename... Args>
void log(const char *s, T value1, Args... args)
while (*s)
if (*s == '%')
if (*(s + 1) == '%')
++s;
else
if ( std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value )
int16_t x = value1;
int16_t x = static_cast<int16_t>(value1);
std::cout << x;
else
std::cout << value1;
log(s + 1, args...); // call even when *s == 0 to detect extra arguments
return;
std::cout << *s++;
throw std::logic_error("extra arguments provided to printf");
但是我得到了错误:
error: invalid static_cast from type ‘std::basic_string<char, std::char_traits<char>,
std::allocator<char> >’ to type ‘int16_t’
有没有不打印ASCII的?
【问题讨论】:
我看到的问题是x
被声明了两次。
这是我尝试投射的两种方式。只是在玩。错误如所述。它不会编译。
好吧,奇怪。我正在使用 GCC 4.4.6
把实际存在你描述的问题的代码贴出来怎么样?
【参考方案1】:
If 语句不会在编译时做出决定;编译器将始终检查两个分支。
您需要创建一个重载的 write()
函数,其中默认版本流到 cout,并且您可以为特定类型(例如 char
)重载。
【讨论】:
或者希望优化器消除其中一个分支……虽然不是最可靠的代码编写方式。 @SanderDeDycker 不,如果其中一个分支在特定实例中具有无效代码,这将无济于事。如果只是担心死分支在结果代码中,那么依赖优化器是完全可以的。 Afaik,这取决于编译器(这是我说它不太可靠的原因之一) - 我不认为 C++ 标准要求死代码需要在语法上正确(相对于语义正确)。但是,您可能是对的,实际上大多数编译器会根据它们构建解析树的方式来强制执行这两种方法。 我从来没有听说过编译器会跳过死分支的语义验证,目前的趋势是在验证方面更积极而不是更少。此外,该标准确实要求死代码在语义上是正确的——更具体地说,它要求所有代码在语义上都是正确的,根本没有死代码的概念。 对于我的陈述,我是基于“as-if”规则。具体来说:“一个实际的实现不需要评估表达式的一部分,如果它可以推断出它的值没有被使用并且没有产生影响程序可观察行为的副作用。”无论如何,这主要是一个理论上的论点,我并不打算像这样切线。我很抱歉。【参考方案2】:问题:
就像你的编译器说的:
error: invalid static_cast from type ‘std::basic_string<char, std::char_traits<char>,
std::allocator<char> >’ to type ‘int16_t’
我想你这样调用你的日志函数:
log("my % thing %....", /*my std::string*/ stringToto, 5,/*....*/);
还有问题!
当编译器看到你想将static_cast
一个std::string
转换成一个int16_t
它会产生一个错误!
你做错了什么
这部分:
if ( std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value )
int16_t x = value1;
int16_t x = static_cast<int16_t>(value1);
std::cout << x;
else
std::cout << value1;
为什么?事实上,即使你的条件 (std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value
) 为假,你的编译器也会解释你的static_cast
你应该怎么做
使用获取参数(无论其类型如何)并生成 std::string 的函数,如下所示:
template<typename T>
std::string
my_to_string(T) return ("what is this type?");
template<>
std::string
my_to_string(std::string s) return (s);
template<>
std::string
my_to_string(int integer) return (std::to_string(integer));
然后在你的日志函数中调用它,如下所示: std::cout
祝你工作顺利!
【讨论】:
是的,我的一些值是字符串。我忘记了那些。谢谢。我会这样做的。【参考方案3】:您似乎使用std::string
调用您的函数,它无法转换为int16_t
。除了static_cast
,您可以使用以下为字符串重载的函数模板:
template<typename T>
auto cast_to_int(T const& t) -> int16_t
return static_cast<int16_t>(t);
auto cast_to_int(std::string const& t) -> int16_t
std::istringstream ss(Text);
int16_t result;
ss >> result;
return result;
最终,您必须为更多类型重载它。
调用上述方法
std::cout<< cast_to_int(value1);
而不是整个块
if ( std::is_same<T, uint8_t>::value || std::is_same<T, int8_t>::value )
int16_t x = value1;
int16_t x = static_cast<int16_t>(value1);
std::cout << x;
else
std::cout << value1;
【讨论】:
以上是关于无效的静态演员表的主要内容,如果未能解决你的问题,请参考以下文章