如何在c++中使用if-else和类型初始化

How to use if else along with type initialisation in c++?

本文关键字:if-else 类型 初始化 c++      更新时间:2023-10-16

考虑一个可以使用初始化的类"myArbPrec"

myArbPrec("0.1");

(例如,它表示任意精度类型)。

我希望我的代码与myArbPrecdouble都兼容。用户使用模板设置类型。

程序中使用的模板类中有一些常量,例如0.1。这些常数将以用户选择的相应类型表示。

我的问题是:如何在根据所选类型初始化的代码中放入常量?具体来说,对于myArbPrec,应该将其初始化为myArbPrec("0.1")。对于double,应将其初始化为double(0.1)

问题是我不能使用myArbPrec(0.1),因为这会先将转换为两倍,可能会失去精度,然后才转换为myArbPrec。因此,如果我的模板参数是T,我就不能写T(0.1)。但由于double("0.1")在语法上不正确,我也不能使用T("0.1")

到目前为止,我试图通过写这样的东西来调整这个答案以适应我的问题:

template<typename T>
T atof(const char * c) {
    if (typeid(T) == typeid(double))
        return std::atof(c);
    else
        return T(c);
}

然而,这失败了,因为即使typeid(T) == typeid(double)总是false,else分支仍然被编译,这使得即使Tdouble,这也会失败。

使用atof函数的互斥SFINAE重载:

namespace foo {
  template<typename T>
  typename std::enable_if<std::is_same<T, double>::value, T>::type atof(const char * c) {
    return std::atof(c);
  }
  template<typename T>
  typename std::enable_if<!std::is_same<T, double>::value, T>::type atof(const char * c) {
    return T(c);
  }
}

我认为使用C++17,您将能够将原始模板与if constexpr一起使用,这将起作用。

提议的文件在这里。

我没有编译器来测试它。

作为@101010建议的替代解决方案,您可以使用标签调度和重载函数:

#include<type_traits>
#include<utility>
#include<cstdlib>
#include<iostream>
template<typename>
struct tag {};
double atof(tag<double>, const char *c) {
    std::cout << "double" << std::endl;
    return std::atof(c);
}
template<typename T>
T atof(tag<T>, const char * c) {
    std::cout << "something else" << std::endl;
    return T{c};
}
template<typename T>
T atof(const char * c) {
    return atof(tag<std::decay_t<T>>{}, c);
}
int main() {
    atof<double>("3.1");
    atof<std::string>("bar");
}