C++ 在不重载的情况下确定Visual Studio 2008中模板参数的类型

C++ 在不重载的情况下确定Visual Studio 2008中模板参数的类型,c++,visual-studio,templates,C++,Visual Studio,Templates,我知道以前有人问过这个问题,但我正试图明确地找出它是否可以在Visual Studio 2008 SP1(C++版本9)中解决,而不需要函数重载,也不需要boost或其他第三方库 template<typename T>T foo() { #if (T is char*) // return something #elif (T is int) // return something different . . . #endif } template

我知道以前有人问过这个问题,但我正试图明确地找出它是否可以在Visual Studio 2008 SP1(C++版本9)中解决,而不需要函数重载,也不需要boost或其他第三方库

template<typename T>T foo()
{
    #if (T is char*) // return something
    #elif (T is int) // return something different
    . . .
    #endif
}
templatetfoo()
{
#如果(T是char*)//返回一些内容
#elif(T是int)//返回不同的内容
. . .
#恩迪夫
}
T可以是简单的内置类型(不是类)。不需要T型输入参数

出于某种原因,编译器告诉“is_same”:它不是“std::tr1”的成员。也许,is_same是在VisualStudio2008SP1之后引入的,尽管理论上它应该是可用的

我想知道这是否是另一项“不可能”的任务。
谢谢

我不知道MSVC的那个版本,但假设您没有
std::is_same
,那么自己编写它就相当简单了:

#include <iostream>

template <typename T,typename U>
struct is_same {
    static const bool value = false;
};
template <typename T>
struct is_same<T,T> {
    static const bool value = true;
};

int main() {
    std::cout << is_same<int,int>::value << '\n';
    std::cout << is_same<int,double>::value << '\n';
}

这就是我想要的:

template <typename T,typename U>
struct is_same
{
    static const bool value = false;
};
template <typename T>
struct is_same<T,T> {
    static const bool value = true;
};

class INI
{
public:
    . . .
    template<typename T> T    getValue(LPCTSTR path, T    deflt);
    template<bool>       bool getValue(LPCTSTR path, bool deflt);
private:
    LPCTSTR data;
};

template<typename T> T INI::getValue(LPCTSTR path, T deflt)
{
    if (is_same<T, _int64>::value)          return (T)_strtoi64(data, NULL, 10);
    if (is_same<T, unsigned _int64>::value) return (T)_strtoui64(data, NULL, 10);
    if (is_same<T, int>::value            ||
        is_same<T, short>::value          ||
        is_same<T, char>::value)            return (T)strtol(data, NULL, 10);
    if (is_same<T, unsigned int>::value   || 
        is_same<T, unsigned short>::value || 
        is_same<T, unsigned char>::value)   return (T)strtoul(data, NULL, 10);
    if (is_same<T, double>::value         ||
        is_same<T, float>::value)           return (T)atof(data);
    return deflt;
}
template<> bool INI::getValue(LPCTSTR path, bool deflt)
{
    return (data[0] == '1') ? true : (data[0] == "0") ? false : deflt;
}
模板
结构是相同的
{
静态常量布尔值=假;
};
模板
结构是相同的{
静态常量布尔值=真;
};
INI类
{
公众:
. . .
模板T getValue(LPCTSTR路径,T deflt);
模板bool getValue(LPCTSTR路径,bool deflt);
私人:
LPCTSTR数据;
};
模板T INI::getValue(LPCTSTR路径,T deflt)
{
if(is_same::value)返回(T)_stroi64(数据,NULL,10);
if(is_same::value)返回(T)_stroui64(数据,NULL,10);
如果(是相同的::值||
值是否相同||
is_same::value)返回(T)strtol(数据,NULL,10);
如果(是相同的::值| |
|u相同::值||
is_same::value)返回(T)strtoul(数据,NULL,10);
如果(是相同的::值||
is_same::value)返回(T)atof(数据);
回撤;
}
模板bool INI::getValue(LPCTSTR路径,bool deflt)
{
返回(数据[0]==“1”)?真:(数据[0]==“0”)?假:定义;
}

在新的C++编译器中,我删除了ISSH相同的声明,插入了STD::在每个ISI相同之前,所有的工作方式都相同。

和,看起来,T类的函数参数至少是需要的,对于旧的C++编译器来说,


谢谢

为什么不直接实现呢?你可以为你想处理的每一个特殊情况提供模板专门化,类似于重载。我试过-编译器不接受它(我写过)。这是干净的VisualStudio2008WITSP1安装。我想它应该是可用的,但它不是。我不确定如果constexpr(C++17)或多个专门化,它是否可以在没有
的情况下工作。像
#if
这样的预处理器指令没有帮助。如果不使用
if constexpr
,则必须使每个分支对每个模板参数都有效,因此只能返回彼此之间可转换的类型。否则一个分支将无效,比如在
foo
中尝试
返回char*
,我删除了它,因为我犯了一个愚蠢的错误。它不“工作”。在声明为返回的函数中,不能返回
int
,例如
std::string
。解决方案取决于更多细节。你想退货什么?<代码> t>代码>是什么类型?STR::在C++版本11中添加了ISSY。理论上,我正在使用的版本9应该有std::tr1::是相同的,但它不编译。我在问题中提到过。@AndreiKalantarian我已经阅读了问题,但是由于您没有显示代码或编译器错误,我无法知道您的代码有什么问题。在任何版本的编译器(afaik)@AndreiKalantarian中,我的答案都应该是正确的。我没有在代码中使用
std::is_same
,如果这是您的意思……您的示例代码与问题的不匹配。这个问题是关于函数模板的,你的答案给出了一个类模板(带有成员函数,但这与函数模板不同)。既然这是你的问题,我毫不怀疑这段代码解决了你的特殊情况。但是,对于未来有类似问题的读者来说,这可能会很糟糕。与问题不匹配的关键部分是,在您的解决方案中,函数采用了一个参数,而不是在问题中。如果函数使用了<代码> T >代码>作为PalMaver,你应该简单地使用重载。我在C++和JavaScript编码多年之后回到C++,并为不精确的术语道歉(尽管我尝试过)。不,我不是在找类模板。模板方法进入大型遗留类。原始问题中的代码示例与最终的生产代码sans函数参数匹配(我删除了一些不相关的内容)。关键部分是检查模板函数中的变量类型。没想到它会那么便携。再次感谢@idclev发布解决方案@AndreiKalantarian注意到我从回答中删除了我认为有问题的部分。你用它做什么是你的事;)。说真的,我永远不会让你的
INI::getvalue
通过代码审查,因为我不明白为什么不能用重载完成,你的方法模板假装对所有
T
都很好,但事实并非如此。无论如何,可能有一些约束我不知道,我很高兴能够帮助大家,因为重载是为了保持类定义的简单:事实上,每个重载都应该加倍以处理LPCWSTR和LPCSTR。拥有大量的新定义对项目来说不太合适——尽管从功能上来说它更干净。起初,我希望不使用类型为T的参数(默认值通常为0),但看起来这是不可能的,或者总体上很复杂。
template <typename T,typename U>
struct is_same
{
    static const bool value = false;
};
template <typename T>
struct is_same<T,T> {
    static const bool value = true;
};

class INI
{
public:
    . . .
    template<typename T> T    getValue(LPCTSTR path, T    deflt);
    template<bool>       bool getValue(LPCTSTR path, bool deflt);
private:
    LPCTSTR data;
};

template<typename T> T INI::getValue(LPCTSTR path, T deflt)
{
    if (is_same<T, _int64>::value)          return (T)_strtoi64(data, NULL, 10);
    if (is_same<T, unsigned _int64>::value) return (T)_strtoui64(data, NULL, 10);
    if (is_same<T, int>::value            ||
        is_same<T, short>::value          ||
        is_same<T, char>::value)            return (T)strtol(data, NULL, 10);
    if (is_same<T, unsigned int>::value   || 
        is_same<T, unsigned short>::value || 
        is_same<T, unsigned char>::value)   return (T)strtoul(data, NULL, 10);
    if (is_same<T, double>::value         ||
        is_same<T, float>::value)           return (T)atof(data);
    return deflt;
}
template<> bool INI::getValue(LPCTSTR path, bool deflt)
{
    return (data[0] == '1') ? true : (data[0] == "0") ? false : deflt;
}