(我认为这不是模板成员模板类的功能专业化,而无需指定类模板参数
阅读有点困难,所以我可能错了。我还没有发现其他可能的相关问题)
是否有一种方法可以根据实例模板类型过载功能?
就我而言,我有一个数字类,可以实现模型操作员
template <typename X>
class Operand
{
private:
X _val;
public:
Operand *operator% (const Operand &other_number ) const
{
//here, i would like use fmod for floats and doubles, and % for integers
}
];
,当然,总有一种解决方案,将所有内容施放成长双打,使用FMOD并将其铸造回X,但感觉
- 非常效率非常低
- ,非常尴尬
- 并不是很谨慎,对C ++
- 和C ++和可能以某种方式容易出现问题
(i don't think it's a duplicate of Template member function specialization of a templated class without specifying the class template parameter
reading it was a bit difficult, so i might be wrong. i also found no other possibly relevant questions)
is there a way to overload functions based on the instances template type?
in my case, i have a number class that implements a modulo operator
template <typename X>
class Operand
{
private:
X _val;
public:
Operand *operator% (const Operand &other_number ) const
{
//here, i would like use fmod for floats and doubles, and % for integers
}
];
of course, there's always the solution of casting everything into long doubles, using fmod, and casting back into X, but it feels
- terribly inefficient
- Very awkward
- not very idiomatic to C++
- and probably pretty problem prone somehow
发布评论
评论(4)
您在寻找这样的东西吗?
丑陋的解决方案,但也许这是您想要的。我的意思是,如果案件的数量不会改变,那么可能还可以。
但是,我会质疑总体设计并寻找诸如 CPO 。
如果您寻找一种“基于过载的”解决方案,那么您可以将所需的各种类型的
operator%
专业化:不用说,这也是一个丑陋的解决方案。
Are you looking for something like this?
Ugly solution, but maybe it's what you're looking for. I mean, if the number of cases is not gonna change, then it's probably ok.
However, I would question the overall design and look for topics like CPO.
If you look for an "overload-based" solution, than you can specialize the
operator%
for the various types you need:Needless to say, this is a ugly solution as well.
当我提到cpos 在另一个答案中,我指的是Taht Taht tht the href =“ https://stackoverflow.com/questions/63818871/why-does-tag-ing-invoke-pattern-need-the-niebloid-s-niebloid-stdtag-invoke-at-al-all”>在这里。
但是,即使不遵循这些长度,我们也可以汲取一些灵感:
操作数&lt; t&gt; :: operator%
根据helper
function 在_VAL
s 上作用于operator%
的参数,并传递给helper
,helper
(_VAL
)您要启用的类型>;操作员%
中,调用helper
应为 不合格的 ,它具有可以依靠ADL的优势只要匹配的助手
过载和至少一个参数类型在同一命名空间中定义(不一定是相同;用于详细信息的ADL),就可以成功呼叫。helper
(例如,如果您打算使用Operand&lt&std :: vector&lt ; int&gt;&gt;
,您无法在namespace std {/ * shere */}
中定义helper
,因为那是非法),令助手
采用类型操作数
的第一个additonal参数,该参数可作为标签,允许您在中定义
的名称空间。helper
操作数这是一个粗略的尝试:
但是我真的建议您通过我链接的那些读物以及从那里链接的那些读物。 CPO在通用编程中最重要。
When I mentioned CPOs in the other answer, I was referring to techniques taht are discussed a bit here.
However, even without going to those lengths, we can take just some inspiration:
Operand<T>::operator%
in terms of ahelper
function acting on the_val
s which are extracted fromoperator%
's arguments and passed tohelper
,helper
for the types (of_val
) you want to enable;operator%
, the call tohelper
should be unqualified, which has the advantage that you can rely on ADL for the call to be successful as long as the matchinghelper
overload and at least one argument's type are in defined in the same namespace (well, not necessarily the same; study ADL for the details);helper
in the same namespace as the argument you want to use it on (e.g., if you were planning to useOperand<std::vector<int>>
, you can't definehelper
innamespace std { /* here */ }
because that's illegal), lethelper
take a first additonal argument of typeOperand
, which acts as a tag and allows you to definehelper
inOperand
's namespace.Here's a rough attempt:
But I really suggest to go through those readings I linked and those linked from there. CPOs are most important in generic programming.
由于C ++ 17,因此使用
如果ConstexPr
非常实用。但是,如果您有很多差异,则可能需要将浮点实现与积分类型实现分开。以下所有实现都需要
#include&lt; type_traits&gt;
,也应遵循此免费功能:一种方法是使用
CRTP,看起来可能是这样的:
如果您想使用:
由于C ++ 17,使用 constexpr,如果 通常比sfinae方法更喜欢:
Since C++17, using
if constexpr
is very practical. Though, if you have many differences you may want to separate the floating point implementation from the integral type implementation completely.All the below implementations require
#include <type_traits>
and should also be followed by this free function:One way of doing it would be to use the CRTP:
Without CRTP, it could look like this:
If you want to select the member function implementation using SFINAE:
Since C++17, using constexpr if is often preferred over the SFINAE method:
我认为,基于模板类型的函数超载的最干净的方法是使用C ++ 20约束。您可以执行以下操作:
请注意,这也使用非成员的朋友定义,在我看来,这更像是对称性,更易于阅读。
如果您没有C ++ 20编译器,则可以使用
std :: Enable_if
进行完全相同的效果(但是,如果找不到匹配的操作员,则使用丑陋的编译器错误消息)。std :: enable_if
可以以各种方式使用,我更喜欢以下一个:如果您发现自己为更多运算符/函数进行此操作,则应该完全分开针对不同类型的实现,如Ted Lyngmo的答案中所示。
I think the cleanest way to overload a function based on a template type is using the C++20 constraints. You can do something like the following:
Note that this also uses non-member friend definitions, which is more symmetric and easier to read in my opinion.
If you don't have a C++20 compiler, you can use
std::enable_if
for exactly the same effect (but with uglier compiler error messages if no matching operator is found).std::enable_if
can be used in various ways, from which I prefer the following one:If you find yourself doing this for many more operators/functions, you should propably completely separate the implementations for the different types, like e.g. shown in the answer of Ted Lyngmo.