带有模板参数enable_if的C++朋友函数。

问题描述 投票:0回答:1

我正在为一个结构的朋友函数而苦恼,这个结构的模板参数为 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中定义是可行的,但我想学习如何使用带有类型特征的模板友函数。

c++ templates friend typetraits friend-function
1个回答
1
投票

朋友声明指的是非模板操作符,而类定义出来的定义指的是模板的,它们不匹配。

你可能需要

// 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);
}

生活

© www.soinside.com 2019 - 2024. All rights reserved.