在 C++ 11 中,我想创建一个具有两个专业化的模板别名,每个专业化解析为不同的函数。
void functionA();
void functionB();
template<typename T = char>
using Loc_snprintf = functionA;
template<>
using Loc_snprintf<wchar_t> = functionB;
Run Code Online (Sandbox Code Playgroud)
所以我可以打电话给eg Loc_snprintf<>(),它决定了functionA()。
显然似乎不可能(编译)。是否有一些最终简单的东西可以模仿它(也许使用类模板)?
我有以下小的 C++ 代码示例,但我无法弄清楚为什么编译器以这种方式工作,尽管我花了很多时间研究 cppreference。我将不胜感激任何解释!神箭
#include <type_traits>
template<typename Tp>
struct depend_type
{
constexpr static bool false_ = false;
};
template<typename Tp>
struct cont
{
using x = void;
static_assert(std::is_same_v<Tp, int>);
// if uncomment, will be complie error -> 'cont<Tp>::x' instantiated with 'void (*p)(int) = func;'
// static_assert(depend_type<Tp>::false_);
};
template<typename Tp>
void func(Tp)
{
}
template<typename Tp>
typename cont<Tp>::x func(Tp);
int main(int /* argc */, char * /*argv*/[])
{
// func(1); is ambiguous call
void (*p)(int) = func; // why is …Run Code Online (Sandbox Code Playgroud) c++ function-templates overload-resolution template-meta-programming
周期性地让我感到沮丧的C++的一个方面是决定模板在头文件(传统上描述接口)和实现(.cpp)文件之间的位置.模板通常需要进入标题,暴露实现,有时会引入额外的标题,以前只需要包含在.cpp文件中.我最近又遇到了这个问题,下面显示了它的简化示例.
#include <iostream> // for ~Counter() and countAndPrint()
class Counter
{
unsigned int count_;
public:
Counter() : count_(0) {}
virtual ~Counter();
template<class T>
void
countAndPrint(const T&a);
};
Counter::~Counter() {
std::cout << "total count=" << count_ << "\n";
}
template<class T>
void
Counter::countAndPrint(const T&a) {
++count_;
std::cout << "counted: "<< a << "\n";
}
// Simple example class to use with Counter::countAndPrint
class IntPair {
int a_;
int b_;
public:
IntPair(int a, int b) : a_(a), b_(b) {}
friend std::ostream & …Run Code Online (Sandbox Code Playgroud) 任何人都可以解释为什么在第三版C++编程语言的第13章中,Stroustrup说明了函数模板的默认参数,尽管C++(pre C++ 11)不支持它们?这是Stroustrup在第13.4.1节中给出的示例:
明确指定每个调用的比较是繁琐的.幸运的是,很容易选择默认值,因此只需要明确指定不常见的比较条件.这可以通过重载来实现:
Run Code Online (Sandbox Code Playgroud)template<class T, class C> int compare(const String<T>& str1, const String<T>& str2); // compare using C template<class T> int compare(const String<T>& str1, const String<T>& str2); // compare using Cmp<T>或者,我们可以提供普通约定作为默认模板参数:
Run Code Online (Sandbox Code Playgroud)template <class T, class C = Cmp<T> > int compare(const String<T>& str1, const String<T>& str2)
这是编译器错误:
错误:默认模板参数可能不在函数模板中使用
请考虑以下代码:
#include <iostream>
struct S {
void f(const char* s) {
std::cout << s << '\n';
}
};
template <typename... Args, void(S::*mem_fn)(Args...)>
void invoke(S* pd, Args... args) {
(pd->*mem_fn)(args...);
}
int main() {
S s;
void(*pfn)(S*, const char*) = invoke<const char*, &S::f>;
pfn(&s, "hello");
}
Run Code Online (Sandbox Code Playgroud)
编译代码时,clang会出现以下错误:
main.cpp:16:33: error: address of overloaded function 'invoke' does not match required type 'void (S *, const char *)'
void(*pfn)(S*, const char*) = invoke<const char*, &S::f>
^~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:10:6: note: candidate template ignored: invalid explicitly-specified argument …Run Code Online (Sandbox Code Playgroud) c++ language-lawyer function-templates variadic-templates c++11
我想定义一个类模板的函数模板.代码看起来像这样.
template<int M>
struct test{
private:
int value;
template<int N = 2 * M>
friend auto foo(test const t){
test<N> r;
r.value = t.value;
return r;
}
};
int main(){
test<1> t;
foo(t);// expected to return test<2>
foo<1>(t);// expected to return test<1>
foo<3>(t);// expected to return test<3>
}
Run Code Online (Sandbox Code Playgroud)
但它不会编译.与以前的问题相比,下面列出了差异.
编译错误g++ -std=c++1z:
a.cpp: In instantiation of 'auto foo(test<M>) [with int N = 2; int M = 1]':
a.cpp:16:10: required from here
a.cpp:4:9: error: 'int test<2>::value' is private …Run Code Online (Sandbox Code Playgroud) c++ templates friend-function function-templates class-template
我有一个带有一个高度模板化的免费函数的名称空间,例如:
namespace a
{
template<typename T, typename K, typename H>
void f(T t, K k, std::vector<H> h_vec = {})
{ /* body */ }
}
Run Code Online (Sandbox Code Playgroud)
在另一个命名空间中,为了方便起见,我想为一堆特定用法使用一些别名,例如:
namespace b
{
using my_specific_f = a::f<int,string,char>;
}
Run Code Online (Sandbox Code Playgroud)
这将使我能够为函数提供更好的命名,因为f在我正在研究的代码库中这是非常通用的(请记住,我在这里仅提供简化的示例来说明这一点)。但是不幸的是,这显然是语言所禁止的。
因此,在第二次尝试中,我尝试使用函数指针:
namespace b
{
auto my_specific_f = &a::f<int,string,char>
}
Run Code Online (Sandbox Code Playgroud)
这通常可以正常工作,但是在我的情况下,由于f没有一个默认参数,因此我认为它不会导致该函数具有一个以上的函数指针(在本例中为两个),并且只能使用三个参数版本。
此时,我只是放弃了,只是简单地my_specific_f将其体内的调用重定向到f:
namespace b
{
void my_specific_f(int i, string s, vector<char> v = {} )
{
a::f(i,s,v);
}
}
Run Code Online (Sandbox Code Playgroud)
但是我不太喜欢这种解决方案,因为它会导致较少的可维护性,以防万一f要更改其签名,因为所有重定向功能都需要进行协调调整,而我最初的计划是创建多个别名。
我还有什么可以尝试的吗?在将来的标准发布中甚至可能还是可能?
我有多个类(Foo和Bar这里简单)
struct Bar {};
struct Foo {};
Run Code Online (Sandbox Code Playgroud)
和一个采用单个模板参数并根据该类型执行某些操作的函数:
template <typename T>
constexpr void doSomething() { cout << "Am I a Foo? " << is_same<T,Foo>::value << endl; }
Run Code Online (Sandbox Code Playgroud)
在我的代码中,为我提供了Foos和Bars 的模板参数包,并且应该doSomething()在它们的每个参数上调用函数(我不在乎函数的执行顺序)。
doStuff<Foo, Bar, Bar>(); // --> True / False / False
Run Code Online (Sandbox Code Playgroud)
到目前为止,我唯一能想到的解决方案是:
template <typename... Ts>
class Doer;
template <>
struct Doer <> {
static constexpr void doStuff() {}
};
template <typename Head, typename... Tail>
struct Doer <Head, Tail...> {
static constexpr void …Run Code Online (Sandbox Code Playgroud) c++ variadic-functions function-templates template-meta-programming variadic-templates
template <typename T>
void show(T&); // #1
template <typename T>
void show(T const&); // #2
int main()
{
int a = 0;
show(a); // #1 to be called
}
Run Code Online (Sandbox Code Playgroud)
我对这些偏序规则感到困惑。以下是一些引用:[temp.deduct.partial]/5
在完成偏序之前,对用于偏序的类型执行某些转换:
如果
P是引用类型,P则替换为引用的类型。如果
A是引用类型,A则替换为引用的类型。
如果
P和A都是引用类型(在被上面提到的类型替换之前),确定这两种类型中的哪一种(如果有的话)比另一个更符合 cv 限定;否则,出于偏序目的,这些类型被视为同样具有 cv 限定。下面将使用该确定的结果。
删除任何顶级 cv 限定符:
如果
P是 cv 限定类型,P则替换为 的 cv 非限定版本P。如果
A是 cv 限定类型,A则替换为 的 cv 非限定版本A。 …
c++ partial-ordering language-lawyer function-templates template-argument-deduction
这个问题继续 非静态数据成员类推导
这是未命名的参数函数,我用它来返回std::string数据类型的表示
struct Boo {};
struct Foo {};
std::string class2str(const double) { return "Floating"; };
std::string class2str(const int) { return "Fixed Point"; };
std::string class2str(const Foo) { return "Class Foo"; };
std::string class2str(const Boo) { return "Class Boo"; };
int main(int argc, char* argv[])
{
int x_a;
double x_b;
Foo F;
Boo B;
std::cout << "x_a :" << class2str(x_a) << std::endl;
std::cout << "x_b :" << class2str(x_b) << std::endl;
std::cout << "Foo :" << class2str(F) << std::endl; …Run Code Online (Sandbox Code Playgroud)