条件编译和非类型模板参数

时间:2015-04-23 04:59:18

标签: c++ templates metaprogramming

我无法理解非类型模板参数,并希望有人可以阐明这一点。

#include <iostream>

template<typename T, int a>
void f() {
  if (a == 1) {
    std::cout << "Hello\n";
  } else {
    T("hello");
  }
}

int main() {
  f<int, 1>;
}

当我编译它时,我收到一个错误说:

/tmp/conditional_templates.cc:13:12:   required from here
/tmp/conditional_templates.cc:8:5: error: cast from ‘const char*’ to ‘int’ loses precision [-fpermissive]
     T("hello");
     ^

但是,编译器不能检测到非类型参数“a”为1,因此不会采用else分支吗?或者说这太过于期待了?在这种情况下,我该如何完成这样的事情?

3 个答案:

答案 0 :(得分:3)

我必须承认,老实说,我没有看到这样做的根本原因,而是你的代码。除了明显的错误(无法为main()中的函数调用提供parens,以及警告(将char地址转换为int的数据丢失),关于条件包含的更大问题很重要。< / p>

如果您有以下代码:

if (something)
{
    do something
}

显然必须编译,并且有条件地这样做。 something源自非类型模板参数没有任何区别。您需要从函数内的if-expression中获取逻辑,而不是从模板扩展控制机制中获取逻辑。专业化是一种这样的技术,SFINAE是另一种技术:

#include <iostream>
#include <iomanip>
#include <type_traits>
#include <cstdint>

static const char* something = "something";

template<class T, bool a>
typename std::enable_if<a>::type f()
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    std::cout << something << '\n';
}

template<class T, bool a>
typename std::enable_if<!a>::type f()
{
    std::cout << __PRETTY_FUNCTION__ << '\n';
    std::cout << std::hex << T(something) << '\n';
}

int main()
{
    f<int, true>();
    f<intptr_t, false>();
}

<强>输出

typename std::enable_if<a>::type f() [T = int, a = true]
something
typename std::enable_if<!a>::type f() [T = long, a = false]
100001f18

你在每个人身上所做的都取决于你。当然,你可以使用预处理器宏进行大量/全部操作,但那里的乐趣在哪里?

答案 1 :(得分:1)

Try this instead:

#include <iostream>
template<typename T, int a>
struct A {
    void f() {
        T("hello");
    }
};

template<typename T>
struct A<T,1> {
    void f() {
        std::cout << "Hello\n";
    }
};


int main() {
  A<int,1> a;
  a.f();
  A<int,2> b;
  b.f();
}

Now, this uses partial template specialization in order to provide alternative implementations for specific values of the template parameters.

Note that I've used a class, because function templates cannot be partially specialized

答案 2 :(得分:0)

Seems that in your environment sizeof(int) is different than sizeof(const char*).

In such case part of code: T("hello") which is in fact int("hello") tries to convert const char* to int. Compiler is complaining because precision would be lost in such a conversion.

To check the sizes of int and const char*:

std::cout << sizeof(int) << std::endl;
std::cout << sizeof(const char*) << std::endl;

else branch won't be run when calling f<int, 1>() but it does not mean that compiler will ignore errors within else code.