函数模板的部分特化

发布于 2024-10-17 08:33:04 字数 1072 浏览 6 评论 0 原文

在下面的代码片段中,

template<typename T1>
void func(T1& t)
{
    cout << "all" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "float" << endl;
}

// I do not want this
// template<> void func(float &t)

int main()
{
    int i; float f;
    func(i); // should print "all"
    func(f); // should print "float" 
    return 0;
}

我希望修改模板,通过传递除 float 之外的任何类型将打印“all”,传递 float 将打印“float”。我不需要模板专业化,而是需要部分专业化,它将根据输入类型进行相应的操作。我该怎么办呢。提前致谢。

我目前面临的情况是这样的, 我需要定义以下内容,

template<typename T1>
void func(T1 &t)
{
    cout << "t1" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "t2" << endl;
}

以下调用应打印“t2”以下

func(int) // print "t2"
func(float) // print "t2"
func(string) // print "t2"

调用应打印“t1”

func(char) // print "t1"
func(xyz) // print "t1"
...
func(abc) // print "t1"

某种类似于上面的分组,其中很少有人应该调用部分专业化实现,而其他人应该调用默认实现。

In the below code snippet,

template<typename T1>
void func(T1& t)
{
    cout << "all" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "float" << endl;
}

// I do not want this
// template<> void func(float &t)

int main()
{
    int i; float f;
    func(i); // should print "all"
    func(f); // should print "float" 
    return 0;
}

I would like to have the templates modified which by passing any type other than float will print "all" and passing float will print "float". I do not want template specialization, instead have partial specialization which will act accordingly based on input type. How should i go about it. Thanks in advance.

Well the scenario, i'm currently facing is like,
I need to have the following defined,

template<typename T1>
void func(T1 &t)
{
    cout << "t1" << endl;
}

template<typename T2>
void func(T2 &t)
{
    cout << "t2" << endl;
}

The following calls should print "t2"

func(int) // print "t2"
func(float) // print "t2"
func(string) // print "t2"

The following calls should print "t1"

func(char) // print "t1"
func(xyz) // print "t1"
...
func(abc) // print "t1"

some kind of grouping like the above where few should call the partial specialization implementation and others should call the default implementation.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

下壹個目標 2024-10-24 08:33:04

您可以将函数重载与模板结合起来。所以:

#include <iostream>

template<typename T>
void func(T& t)
{
    std::cout << "all" << std::endl;
}

void func(float& f)
{
    std::cout << "float" << std::endl;
}

int main()
{
    int i; float f;
    func(i); // prints "all"
    func(f); // prints "float" 
    return 0;
}

You can combine function overloading with templates. So:

#include <iostream>

template<typename T>
void func(T& t)
{
    std::cout << "all" << std::endl;
}

void func(float& f)
{
    std::cout << "float" << std::endl;
}

int main()
{
    int i; float f;
    func(i); // prints "all"
    func(f); // prints "float" 
    return 0;
}
罪#恶を代价 2024-10-24 08:33:04

为您的情况编写一个类型特征类:

template<class T>
struct IsIntFloatOrString {
  enum { value = boost::is_same<T, int>::value
              or boost::is_same<T, float>::value
              or boost::is_same<T, string>::value };
};

使用 boost::enable_if< /a> 和disable_if:

template<typename T1>
typename boost::enable_if<IsIntFloatOrString<T1> >::type
func(T1 &t) {
  cout << "t1" << endl;
}

template<typename T2>
typename boost::disable_if<IsIntFloatOrString<T2> >::type
func(T2 &t) {
  cout << "t2" << endl;
}

Write a type traits class for your condition:

template<class T>
struct IsIntFloatOrString {
  enum { value = boost::is_same<T, int>::value
              or boost::is_same<T, float>::value
              or boost::is_same<T, string>::value };
};

Use boost::enable_if and disable_if:

template<typename T1>
typename boost::enable_if<IsIntFloatOrString<T1> >::type
func(T1 &t) {
  cout << "t1" << endl;
}

template<typename T2>
typename boost::disable_if<IsIntFloatOrString<T2> >::type
func(T2 &t) {
  cout << "t2" << endl;
}
书信已泛黄 2024-10-24 08:33:04

您不能部分特化 C++ 中的函数。

也许这不是您所指的术语。您可以使用 boost::is_same 等模板根据给定的模板参数执行条件逻辑。您还可以在需要使用任何其他类型的任何地方使用 T ,例如在 typeid(T).name() 中:(

template <typename T>
void foo(T&) {
   if (boost::is_same<T, int>::value)
      std::cout << "int lol";
   else
      std::cout << typeid(T).name();
}

尽管我不推荐使用 typeid().name() 因为它的值不是由标准指定的,并且可能与代码中编写的类型、损坏的符号或 Pokerface 的歌词有所不同。)

附录像其他回答者一样,我个人会选择模板专业化本身或只是简单的函数重载。我不知道你为什么反对他们,但这就是他们存在的目的。

You cannot partially specialise functions in C++.

Perhaps this is not the terminology you mean. You can use templates like boost::is_same<T1, T2> to perform conditional logic based on the given template parameter. You can also use T in any place where you'd use any other type, such as in typeid(T).name():

template <typename T>
void foo(T&) {
   if (boost::is_same<T, int>::value)
      std::cout << "int lol";
   else
      std::cout << typeid(T).name();
}

(Although I'd not recommend using typeid().name() as its value is not specified by the standard and can vary from the type written in your code, to a mangled symbol, or the lyrics to Pokerface.)

Addendum Like other answerers, I would personally choose template specialisation itself or just plain ol' function overloading. I don't know why you're averse to them, but that is what they are there for.

幽梦紫曦~ 2024-10-24 08:33:04

正如托马拉克在他的回答中已经说过的那样,你不能部分地特化模板函数,但是如果你将你的函数更改为模板类中的静态成员函数,你就可以做到这一点。

然而,更好的方法是函数重载。

As Tomalak already said in his answer you can not partially specialize a template function, but if you change your function to be a static member function in a template class, you could do it.

However, a better approach would be function overloading.

殤城〤 2024-10-24 08:33:04

这就是如何在任意数量的条件下,在 enable_if 中不使用丑陋的语法 a 和 !b 和 !c 来使其工作。

如果我们知道部分特化不能用于工作函数,而是可以与类一起使用,那么让我们使用类!我们应该对人们隐藏它,但我们可以使用它们!

好的,代码:

#include <type_traits>
#include <iostream>


template <typename T>
class is_int_or_float : public std::integral_constant<bool, std::is_same<T, int>::value || std::is_same<T, float>::value> {
};


template<typename T, typename Enable = void> //(2)
struct Helper {
    static void go(const T&) {
                std::cout << "all"<< std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<is_int_or_float<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "int or float" << std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<std::is_pointer<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "pointer" << std::endl;
        }
};

template<typename T>
void func(const T& arg) {
        Helper<T>::go(arg); // (1)
}
int main() {
        char c;
        int i;
        float f; 
        int* p;
        func(c);
        func(i);
        func(f);
        func(p);
}

(1) 首先,仅针对每种类型调用帮助程序。没有函数的专门化。
(2) 这里我们添加一个虚拟参数。我们不必在调用时指定它,因为它默认为 void
(3) 在 3 中,当我们允许 T 和其他任何内容(或在我们的例子中为 SFINAE)时,我们只给出 void。一件重要的事情是,我们不应该允许某些 T 出现两次或更多次。

注意:

  1. 我们还可以将默认类型更改为 std::true_type,之后我们将能够摆脱 std::enable_if (std::enable_if ;::value> 将更改为 some_trait::type)。我不确定是哪个

  2. 此代码使用了 C++11 中的类型特征。如果您没有 c++11 支持,您可以编写自己的特征或使用 boost

    中的类型特征。

实例

This is how to make it work without ugly syntax a and !b and !c for enable_if in case of arbitrary number of conditions.

If we know that partial specialization don't work work function but work with classes, let's use classes! We should hide it from people, but we can use them!

OK, code:

#include <type_traits>
#include <iostream>


template <typename T>
class is_int_or_float : public std::integral_constant<bool, std::is_same<T, int>::value || std::is_same<T, float>::value> {
};


template<typename T, typename Enable = void> //(2)
struct Helper {
    static void go(const T&) {
                std::cout << "all"<< std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<is_int_or_float<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "int or float" << std::endl;
        }
};

template<typename T>
struct Helper<T, typename std::enable_if<std::is_pointer<T>::value>::type> { // (3)
        static void go(const T&) {
                std::cout << "pointer" << std::endl;
        }
};

template<typename T>
void func(const T& arg) {
        Helper<T>::go(arg); // (1)
}
int main() {
        char c;
        int i;
        float f; 
        int* p;
        func(c);
        func(i);
        func(f);
        func(p);
}

(1) First of all just for every type call helper. No specialization for functions.
(2) Here we add one dummy argument. We don't have to specify it on calling because it's default to void
(3) In 3 we just give void, when we allow T and anything else (or SFINAE as in our case). One important thing is that we shouldn't allow some T twice or more.

Notes:

  1. We can also change default type to std::true_type, after that we will be able to get rid of std::enable_if (std::enable_if<some_trait<T>::value> will be change to just some_trait<T>::type). I'm not sure which

  2. This code uses type traits from C++11. If you don't have c++11 support you may write your own traits or use type traits from boost

Live example

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文