我正在为一个结构的朋友函数而苦恼,这个结构的模板参数为 enable_if
:
// foo.h
#ifndef FOO_H
#define FOO_H
#include <type_traits>
template<
typename T,
typename = typename std::enable_if<std::is_arithmetic<T>::value>::type
>
struct foo {
foo(T bar) : bar(bar) {}
T get() { return bar; }
friend foo operator+(const foo& lhs, const foo& rhs);
// Defining inside a body works:
// {
// return foo(lhs.bar + rhs.bar);
// }
private:
T bar;
};
// None of these work:
// tempate<typename T, typename>
// tempate<typename T>
// tempate<typename T, typename = void>
template<
typename T,
typename = typename std::enable_if<std::is_arithmetic<T>::value>::type
>
foo<T> operator+(const foo<T>& lhs, const foo<T>& rhs)
{
return foo<T>(lhs.bar + rhs.bar);
}
#endif /* ifndef FOO_H */
和
// main.cpp
#include <iostream>
#include "foo.h"
int main()
{
foo<int> f{1};
foo<int> g{2};
std::cout << (f + g).get() << '\n';
return 0;
}
如果我尝试编译,得到以下链接器错误。
Undefined symbols for architecture x86_64:
"operator+(foo<int, void> const&, foo<int, void> const&)", referenced from:
_main in main-5fd87c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
(与 Apple clang version 11.0.3 (clang-1103.0.32.59)
.)
我希望操作符+只对具有相同模板参数的类型起作用,例如,foo只对foo起作用,而对foo或foo不起作用。
我认为这与 这个问题但我有一个困难的时间,试图找出如何解决我的问题.我试过许多模板定义,像 tempate<typename T, typename>
, tempate<typename T>
, tempate<typename T, typename = typename std::enable_if...>
但这些都不行。
正如代码中所评论的那样,在body中定义是可行的,但我想学习如何使用带有类型特征的模板友函数。
朋友声明指的是非模板操作符,而类定义出来的定义指的是模板的,它们不匹配。
你可能需要
// forward declaration of the class template
template<
typename T,
typename X = typename std::enable_if<std::is_arithmetic<T>::value>::type
>
struct foo;
// declaration of the operator template
template<
typename T,
typename = typename std::enable_if<std::is_arithmetic<T>::value>::type
>
foo<T> operator+(const foo<T>& lhs, const foo<T>& rhs);
// definition of the class template
template<
typename T,
typename
>
struct foo {
foo(T bar) : bar(bar) {}
T get() { return bar; }
friend foo operator+<T>(const foo& lhs, const foo& rhs);
// or left the template parameters to be deduced as
friend foo operator+<>(const foo& lhs, const foo& rhs);
private:
T bar;
};
//definition of the operator template
template<
typename T,
typename
>
foo<T> operator+(const foo<T>& lhs, const foo<T>& rhs)
{
return foo<T>(lhs.bar + rhs.bar);
}