简体   繁体   English

模板 function 重载歧义

[英]template function overloading ambiguity

A beginner's question here, so I have the following code这里是初学者的问题,所以我有以下代码

foo.h

enum class Fruit : uint16_t {
    Apple  = 8019U,
    Orange = 8020U,
    Banana = 8021U,
    Cactus = 8022U
};

class Foo {
  public:
    template<typename T> void SetValue(unsigned int location, const T& value);
    template<typename T> void SetValue(unsigned int location, const T* value_ptr);
    template<typename T> void SetValue(Fruit fruit, const T& value);
    template<typename T> void SetValue(Fruit fruit, const T* value_ptr);
}

foo.cpp

template<typename T>
void Foo::SetValue(unsigned int location, const T& value) {
    std::cout << value << std::endl;
}

template<typename T>
void Foo::SetValue(unsigned int location, const T* value_ptr) {
    std::cout << (*value_ptr) << std::endl;
}

template<typename T>
void Foo::SetValue(Fruit fruit, const T& value) {
    SetValue<T>(static_cast<unsigned int>(fruit), value);
}

template<typename T>
void Foo::SetValue(Fruit fruit, const T* value_ptr) {
    SetValue<T>(static_cast<unsigned int>(fruit), value_ptr);
}

#define INSTANTIATE_TEMPLATE(T) \
    template void Foo::SetValue<T>(unsigned int location, const T& value); \
    template void Foo::SetValue<T>(unsigned int location, const T* value_ptr); \
    template void Foo::SetValue<T>(Fruit fruit, const T& value); \
    template void Foo::SetValue<T>(Fruit fruit, const T* value_ptr);

INSTANTIATE_TEMPLATE(int)
INSTANTIATE_TEMPLATE(uint)
INSTANTIATE_TEMPLATE(bool)
INSTANTIATE_TEMPLATE(float)
INSTANTIATE_TEMPLATE(vec2)
INSTANTIATE_TEMPLATE(vec3)
INSTANTIATE_TEMPLATE(vec4)
INSTANTIATE_TEMPLATE(mat2)
INSTANTIATE_TEMPLATE(mat3)
INSTANTIATE_TEMPLATE(mat4)
...

#undef INSTANTIATE_TEMPLATE

main.cpp

int main() {
    Foo foo;

    float bar[7] { 0.0f, 0.15f, 0.3f, 0.45f, 0.6f, 0.75f, 0.9f };
    float baz = 12.5f;

    foo.SetValue(Fruit::Orange, 1.05);  // calling SetValue<double>(Fruit fruit, const double& value)

    foo.SetValue(Fruit::Apple, bar + 3);  // calling SetValue<float*>(Fruit fruit, float *const& value)
    foo.SetValue(Fruit::Cactus, &baz);    // calling SetValue<float*>(Fruit fruit, float *const& value)
}

In the last 2 calls, while I really intended to call在最后 2 个电话中,虽然我真的打算打电话
SetValue<float>(Fruit fruit, const float* value_ptr)

What actually gets called are实际上被称为的是
SetValue<float*>(Fruit fruit, float *const& value)

I'm aware that this is ambiguous because VS Intellisense was not able to color highlight SetValue<T> in the overridden function body, so I tried to write foo.SetValue<float>(Fruit::Cactus, &baz) instead, now the compiler interprets T as float rather than float* , but I wonder if this is a horrible design...... Is there a better approach that doesn't require me to explicitly specify the type of T ?我知道这是模棱两可的,因为 VS Intellisense 无法在被覆盖的 function 主体中为SetValue<T>着色,所以我尝试改写foo.SetValue<float>(Fruit::Cactus, &baz) ,现在编译器将T解释为float而不是float* ,但我想知道这是否是一个可怕的设计......有没有更好的方法不需要我明确指定T的类型? How can I eliminate the ambiguity completely?我怎样才能完全消除歧义?

I'm aware that this is ambiguous我知道这是模棱两可的

It is not.它不是。

const T& value is a better match than const T* value for float* . const T& valuefloat*const T* value更好。 The former is an exact match, whereas the later require a qualification conversion .前者是完全匹配,而后者需要进行限定转换

You might drop the const for pointer:您可以删除指针的const

template<typename T> void SetValue(Fruit fruit, T* value_ptr);

Demo演示

If you do want do use SFINAE.如果您确实想使用 SFINAE。

 template<typename T, std::enable_if_t<!std::is_pointer<T>::value, bool> = false> 
// I don't really know if there is a difference between = true or = false
 void SetValue(unsigned int location, const T& value) {
         std::cout << value << std::endl;
 }

 template<typename T>
 void SetValue(unsigned int location, const T* value_ptr) {
         std::cout << (*value_ptr) << std::endl;
 }

Just use this to replace the above 2 functions(the ones which cout).只需使用它来替换上述 2 个功能(其中 cout 的功能)。 I don't think the 4th function( Fruit fruit, const T* value_ptr ) is necessary.我不认为第四个函数( Fruit fruit, const T* value_ptr )是必要的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM